summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk1
-rw-r--r--api/current.txt14
-rw-r--r--core/java/android/content/Intent.java3
-rw-r--r--core/java/android/hardware/hdmi/HdmiRecordSources.java4
-rw-r--r--core/java/android/util/PathParser.java93
-rw-r--r--core/res/res/values/strings.xml5
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java4
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp3
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp3
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp17
-rw-r--r--libs/hwui/renderthread/RenderThread.h6
-rw-r--r--location/java/android/location/GpsMeasurementListenerTransport.java90
-rw-r--r--location/java/android/location/GpsNavigationMessage.java276
-rw-r--r--location/java/android/location/GpsNavigationMessageEvent.aidl19
-rw-r--r--location/java/android/location/GpsNavigationMessageEvent.java92
-rw-r--r--location/java/android/location/GpsNavigationMessageListenerTransport.java69
-rw-r--r--location/java/android/location/IGpsNavigationMessageListener.aidl26
-rw-r--r--location/java/android/location/ILocationManager.aidl6
-rw-r--r--location/java/android/location/LocalListenerHelper.java109
-rw-r--r--location/java/android/location/LocationManager.java29
-rw-r--r--media/java/android/media/RemoteController.java9
-rw-r--r--media/java/android/media/browse/MediaBrowserItem.java120
-rw-r--r--media/java/android/media/browse/MediaBrowserService.java47
-rw-r--r--media/java/android/media/session/MediaSessionLegacyHelper.java53
-rw-r--r--packages/SystemUI/AndroidManifest.xml13
-rw-r--r--packages/SystemUI/res/layout/recents_task_view.xml3
-rw-r--r--packages/SystemUI/res/values/config.xml8
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIApplication.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeService.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java72
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java9
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java4
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java34
-rw-r--r--services/core/java/com/android/server/job/JobMapReadFinishedListener.java34
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java24
-rw-r--r--services/core/java/com/android/server/job/JobStore.java53
-rw-r--r--services/core/java/com/android/server/location/GpsLocationProvider.java55
-rw-r--r--services/core/java/com/android/server/location/GpsMeasurementsProvider.java3
-rw-r--r--services/core/java/com/android/server/location/GpsNavigationMessageProvider.java48
-rw-r--r--services/core/java/com/android/server/location/GpsStatusListenerHelper.java4
-rw-r--r--services/core/java/com/android/server/location/RemoteListenerHelper.java39
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java186
-rw-r--r--services/core/jni/com_android_server_location_GpsLocationProvider.cpp127
-rw-r--r--services/tests/servicestests/src/com/android/server/job/JobStoreTest.java (renamed from services/tests/servicestests/src/com/android/server/task/TaskStoreTest.java)102
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java14
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl12
-rw-r--r--tests/VectorDrawableTest/AndroidManifest.xml2
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable01.xml2
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable03.xml28
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable04.xml32
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable05.xml24
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable07.xml6
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable09.xml2
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable10.xml8
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml4
65 files changed, 1560 insertions, 836 deletions
diff --git a/Android.mk b/Android.mk
index 7dfa6a0c67a8..278e67f9649a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -297,6 +297,7 @@ LOCAL_SRC_FILES += \
location/java/android/location/IGeocodeProvider.aidl \
location/java/android/location/IGeofenceProvider.aidl \
location/java/android/location/IGpsMeasurementsListener.aidl \
+ location/java/android/location/IGpsNavigationMessageListener.aidl \
location/java/android/location/IGpsStatusListener.aidl \
location/java/android/location/IGpsStatusProvider.aidl \
location/java/android/location/ILocationListener.aidl \
diff --git a/api/current.txt b/api/current.txt
index f1c42e77e707..84f9912e4071 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16202,7 +16202,7 @@ package android.media.browse {
method public int describeContents();
method public android.os.Bundle getExtras();
method public int getFlags();
- method public int getIconResId();
+ method public int getIconResourceId();
method public android.net.Uri getIconUri();
method public java.lang.CharSequence getSummary();
method public java.lang.CharSequence getTitle();
@@ -16219,7 +16219,7 @@ package android.media.browse {
ctor public MediaBrowserItem.Builder(android.net.Uri, int, java.lang.CharSequence);
method public android.media.browse.MediaBrowserItem build();
method public android.media.browse.MediaBrowserItem.Builder setExtras(android.os.Bundle);
- method public android.media.browse.MediaBrowserItem.Builder setIconResId(int);
+ method public android.media.browse.MediaBrowserItem.Builder setIconResourceId(int);
method public android.media.browse.MediaBrowserItem.Builder setIconUri(android.net.Uri);
method public android.media.browse.MediaBrowserItem.Builder setSummary(java.lang.CharSequence);
}
@@ -16230,15 +16230,17 @@ package android.media.browse {
method public android.media.session.MediaSession.Token getSessionToken();
method public void notifyChildrenChanged(android.net.Uri);
method public android.os.IBinder onBind(android.content.Intent);
- method protected abstract android.media.browse.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
- method protected abstract android.graphics.Bitmap onGetThumbnail(android.net.Uri, int, int);
- method protected abstract java.util.List<android.media.browse.MediaBrowserItem> onLoadChildren(android.net.Uri);
+ method public abstract android.media.browse.MediaBrowserService.BrowserRoot onGetRoot(java.lang.String, int, android.os.Bundle);
+ method public abstract android.graphics.Bitmap onGetThumbnail(android.net.Uri, int, int);
+ method public abstract java.util.List<android.media.browse.MediaBrowserItem> onLoadChildren(android.net.Uri);
method public void setSessionToken(android.media.session.MediaSession.Token);
field public static final java.lang.String SERVICE_ACTION = "android.media.browse.MediaBrowserService";
}
- public static class MediaBrowserService.BrowserRoot {
+ public static final class MediaBrowserService.BrowserRoot {
ctor public MediaBrowserService.BrowserRoot(android.net.Uri, android.os.Bundle);
+ method public android.os.Bundle getExtras();
+ method public android.net.Uri getRootUri();
}
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 3f705ac66541..287ea35e31e0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2682,8 +2682,7 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.action.QUICK_CLOCK";
/**
- * Broadcast Action: This is broadcast when a user action should request the
- * brightness setting dialog.
+ * Activity Action: Shows the brightness setting dialog.
* @hide
*/
public static final String ACTION_SHOW_BRIGHTNESS_DIALOG =
diff --git a/core/java/android/hardware/hdmi/HdmiRecordSources.java b/core/java/android/hardware/hdmi/HdmiRecordSources.java
index 5a02c34ae59a..685eb170fddb 100644
--- a/core/java/android/hardware/hdmi/HdmiRecordSources.java
+++ b/core/java/android/hardware/hdmi/HdmiRecordSources.java
@@ -483,6 +483,7 @@ public final class HdmiRecordSources {
* </ul>
* @hide
*/
+ @SystemApi
public static final class DigitalServiceSource extends RecordSource {
/** Indicates that a service is identified by digital service IDs. */
private static final int DIGITAL_SERVICE_IDENTIFIED_BY_DIGITAL_ID = 0;
@@ -604,6 +605,7 @@ public final class HdmiRecordSources {
* </ul>
* @hide
*/
+ @SystemApi
public static final class AnalogueServiceSource extends RecordSource {
private static final int EXTRA_DATA_SIZE = 4;
@@ -662,6 +664,7 @@ public final class HdmiRecordSources {
* </ul>
* @hide
*/
+ @SystemApi
public static final class ExternalPlugData extends RecordSource {
private static final int EXTRA_DATA_SIZE = 1;
@@ -706,6 +709,7 @@ public final class HdmiRecordSources {
* </ul>
* @hide
*/
+ @SystemApi
public static final class ExternalPhysicalAddress extends RecordSource {
private static final int EXTRA_DATA_SIZE = 2;
diff --git a/core/java/android/util/PathParser.java b/core/java/android/util/PathParser.java
index f4a044861191..c36421db9b06 100644
--- a/core/java/android/util/PathParser.java
+++ b/core/java/android/util/PathParser.java
@@ -54,9 +54,11 @@ public class PathParser {
ArrayList<PathDataNode> list = new ArrayList<PathDataNode>();
while (end < pathData.length()) {
end = nextStart(pathData, end);
- String s = pathData.substring(start, end);
- float[] val = getFloats(s);
- addNode(list, s.charAt(0), val);
+ String s = pathData.substring(start, end).trim();
+ if (s.length() > 0) {
+ float[] val = getFloats(s);
+ addNode(list, s.charAt(0), val);
+ }
start = end;
end++;
@@ -135,6 +137,12 @@ public class PathParser {
list.add(new PathDataNode(cmd, val));
}
+ private static class ExtractFloatResult {
+ // We need to return the position of the next separator and whether the
+ // next float starts with a '-'.
+ int mEndPosition;
+ boolean mEndWithNegSign;
+ }
/**
* Parse the floats in the string.
@@ -148,42 +156,73 @@ public class PathParser {
return new float[0];
}
try {
- float[] tmp = new float[s.length()];
+ float[] results = new float[s.length()];
int count = 0;
- int pos = 1, end;
- while ((end = extract(s, pos)) >= 0) {
- if (pos < end) {
- tmp[count++] = Float.parseFloat(s.substring(pos, end));
+ int startPosition = 1;
+ int endPosition = 0;
+
+ ExtractFloatResult result = new ExtractFloatResult();
+ int totalLength = s.length();
+
+ // The startPosition should always be the first character of the
+ // current number, and endPosition is the character after the current
+ // number.
+ while (startPosition < totalLength) {
+ extract(s, startPosition, result);
+ endPosition = result.mEndPosition;
+
+ if (startPosition < endPosition) {
+ results[count++] = Float.parseFloat(
+ s.substring(startPosition, endPosition));
+ }
+
+ if (result.mEndWithNegSign) {
+ // Keep the '-' sign with next number.
+ startPosition = endPosition;
+ } else {
+ startPosition = endPosition + 1;
}
- pos = end + 1;
- }
- // handle the final float if there is one
- if (pos < s.length()) {
- tmp[count++] = Float.parseFloat(s.substring(pos, s.length()));
}
- return Arrays.copyOf(tmp, count);
- } catch (NumberFormatException e){
- Log.e(LOGTAG,"error in parsing \""+s+"\"");
+ return Arrays.copyOf(results, count);
+ } catch (NumberFormatException e) {
+ Log.e(LOGTAG, "error in parsing \"" + s + "\"");
throw e;
}
}
/**
- * Calculate the position of the next comma or space
+ * Calculate the position of the next comma or space or negative sign
* @param s the string to search
* @param start the position to start searching
- * @return the position of the next comma or space or -1 if none found
+ * @param result the result of the extraction, including the position of the
+ * the starting position of next number, whether it is ending with a '-'.
*/
- private static int extract(String s, int start) {
- int space = s.indexOf(' ', start);
- int comma = s.indexOf(',', start);
- if (space == -1) {
- return comma;
- }
- if (comma == -1) {
- return space;
+ private static void extract(String s, int start, ExtractFloatResult result) {
+ // Now looking for ' ', ',' or '-' from the start.
+ int currentIndex = start;
+ boolean foundSeparator = false;
+ result.mEndWithNegSign = false;
+ for (; currentIndex < s.length(); currentIndex++) {
+ char currentChar = s.charAt(currentIndex);
+ switch (currentChar) {
+ case ' ':
+ case ',':
+ foundSeparator = true;
+ break;
+ case '-':
+ if (currentIndex != start) {
+ foundSeparator = true;
+ result.mEndWithNegSign = true;
+ }
+ break;
+ }
+ if (foundSeparator) {
+ break;
+ }
}
- return (comma > space) ? space : comma;
+ // When there is nothing found, then we put the end position to the end
+ // of the string.
+ result.mEndPosition = currentIndex;
}
/**
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index b41e37c56b7f..31920fa8baa0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4310,8 +4310,9 @@
<!-- Description of a wireless display route. [CHAR LIMIT=50] -->
<string name="wireless_display_route_description">Wireless display</string>
- <!-- Content description of a MediaRouteButton for accessibility support -->
- <string name="media_route_button_content_description">Media output</string>
+ <!-- Content description of a MediaRouteButton for accessibility support.
+ Cast is the standard android verb for sending content to a remote device. [CHAR LIMIT=50] -->
+ <string name="media_route_button_content_description">Cast</string>
<!-- Title of the media route chooser dialog. [CHAR LIMIT=40] -->
<string name="media_route_chooser_title">Connect to device</string>
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 13ef89bc4eb1..8ed6776d395a 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -740,9 +740,7 @@ public class VectorDrawable extends Drawable {
final float minScale = Math.min(scaleX, scaleY);
mFinalPathMatrix.set(vGroup.mStackedMatrix);
- mFinalPathMatrix.postScale(scaleX, scaleY, mViewportWidth / 2f, mViewportHeight / 2f);
- mFinalPathMatrix.postTranslate(
- w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
+ mFinalPathMatrix.postScale(scaleX, scaleY);
vPath.toPath(mPath);
final Path path = mPath;
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index dd34e095738d..763e72747e83 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -85,8 +85,7 @@ int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos
void DrawFrameTask::postAndWait() {
AutoMutex _lock(mLock);
- mRenderThread->queue(this);
- mSignal.wait(mLock);
+ mRenderThread->queueAndWait(this, mSignal, mLock);
}
void DrawFrameTask::run() {
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 6cd3d0bdb96b..91f5801d8b60 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -405,8 +405,7 @@ void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) {
task->setReturnPtr(&retval);
SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition);
AutoMutex _lock(mSyncMutex);
- mRenderThread.queue(&syncTask);
- mSyncCondition.wait(mSyncMutex);
+ mRenderThread.queueAndWait(&syncTask, mSyncCondition, mSyncMutex);
return retval;
}
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 03e98d5b2f03..32dc46ee57eb 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -20,6 +20,7 @@
#include <gui/DisplayEventReceiver.h>
#include <utils/Log.h>
+#include <pthread.h>
#include "../RenderState.h"
#include "CanvasContext.h"
@@ -136,6 +137,7 @@ public:
};
RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
+ , mThreadId(0)
, mNextWakeup(LLONG_MAX)
, mDisplayEventReceiver(0)
, mVsyncRequested(false)
@@ -244,6 +246,7 @@ void RenderThread::requestVsync() {
}
bool RenderThread::threadLoop() {
+ mThreadId = pthread_self();
initThreadLocals();
int timeoutMillis = -1;
@@ -289,6 +292,16 @@ void RenderThread::queue(RenderTask* task) {
}
}
+void RenderThread::queueAndWait(RenderTask* task, Condition& signal, Mutex& lock) {
+ static nsecs_t sTimeout = milliseconds(500);
+ queue(task);
+ status_t err = signal.waitRelative(lock, sTimeout);
+ if (CC_UNLIKELY(err != NO_ERROR)) {
+ ALOGE("Timeout waiting for RenderTherad! err=%d", err);
+ nukeFromOrbit();
+ }
+}
+
void RenderThread::queueAtFront(RenderTask* task) {
AutoMutex _lock(mLock);
mQueue.queueAtFront(task);
@@ -341,6 +354,10 @@ RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
return next;
}
+void RenderThread::nukeFromOrbit() {
+ pthread_kill(mThreadId, SIGABRT);
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index 0b91e9dd97aa..59843736f048 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -23,6 +23,7 @@
#include <set>
#include <cutils/compiler.h>
+#include <utils/Condition.h>
#include <utils/Looper.h>
#include <utils/Mutex.h>
#include <utils/Singleton.h>
@@ -73,6 +74,7 @@ public:
// RenderThread takes complete ownership of tasks that are queued
// and will delete them after they are run
ANDROID_API void queue(RenderTask* task);
+ void queueAndWait(RenderTask* task, Condition& signal, Mutex& lock);
ANDROID_API void queueAtFront(RenderTask* task);
void queueDelayed(RenderTask* task, int delayMs);
void remove(RenderTask* task);
@@ -106,11 +108,15 @@ private:
void dispatchFrameCallbacks();
void requestVsync();
+ // VERY DANGEROUS HANDLE WITH EXTREME CARE
+ void nukeFromOrbit();
+
// Returns the next task to be run. If this returns NULL nextWakeup is set
// to the time to requery for the nextTask to run. mNextWakeup is also
// set to this time
RenderTask* nextTask(nsecs_t* nextWakeup);
+ pthread_t mThreadId;
sp<Looper> mLooper;
Mutex mLock;
diff --git a/location/java/android/location/GpsMeasurementListenerTransport.java b/location/java/android/location/GpsMeasurementListenerTransport.java
index 48a4b4422998..2d9a37273fea 100644
--- a/location/java/android/location/GpsMeasurementListenerTransport.java
+++ b/location/java/android/location/GpsMeasurementListenerTransport.java
@@ -16,99 +16,51 @@
package android.location;
-import com.android.internal.util.Preconditions;
-
-import android.annotation.NonNull;
import android.content.Context;
import android.os.RemoteException;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
/**
- * A handler class to manage transport listeners for {@link GpsMeasurementsEvent.Listener},
- * and post the events in a handler.
+ * A handler class to manage transport listeners for {@link GpsMeasurementsEvent.Listener}.
*
* @hide
*/
-class GpsMeasurementListenerTransport {
- private static final String TAG = "GpsMeasurementListenerTransport";
-
+class GpsMeasurementListenerTransport
+ extends LocalListenerHelper<GpsMeasurementsEvent.Listener> {
private final Context mContext;
private final ILocationManager mLocationManager;
private final IGpsMeasurementsListener mListenerTransport = new ListenerTransport();
- private final HashSet<GpsMeasurementsEvent.Listener> mListeners =
- new HashSet<GpsMeasurementsEvent.Listener>();
public GpsMeasurementListenerTransport(Context context, ILocationManager locationManager) {
+ super("GpsMeasurementListenerTransport");
mContext = context;
mLocationManager = locationManager;
}
- public boolean add(@NonNull GpsMeasurementsEvent.Listener listener) {
- Preconditions.checkNotNull(listener);
-
- synchronized (mListeners) {
- // we need to register with the service first, because we need to find out if the
- // service will actually support the request before we attempt anything
- if (mListeners.isEmpty()) {
- boolean registeredWithServer;
- try {
- registeredWithServer = mLocationManager.addGpsMeasurementsListener(
- mListenerTransport,
- mContext.getPackageName());
- } catch (RemoteException e) {
- Log.e(TAG, "Error handling first listener.", e);
- return false;
- }
-
- if (!registeredWithServer) {
- Log.e(TAG, "Unable to register listener transport.");
- return false;
- }
- }
-
- if (mListeners.contains(listener)) {
- return true;
- }
-
- mListeners.add(listener);
- }
-
- return true;
+ @Override
+ protected boolean registerWithServer() throws RemoteException {
+ return mLocationManager.addGpsMeasurementsListener(
+ mListenerTransport,
+ mContext.getPackageName());
}
- public void remove(@NonNull GpsMeasurementsEvent.Listener listener) {
- Preconditions.checkNotNull(listener);
-
- synchronized (mListeners) {
- boolean removed = mListeners.remove(listener);
-
- boolean isLastListener = removed && mListeners.isEmpty();
- if (isLastListener) {
- try {
- mLocationManager.removeGpsMeasurementsListener(mListenerTransport);
- } catch (RemoteException e) {
- Log.e(TAG, "Error handling last listener.", e);
- }
- }
- }
+ @Override
+ protected void unregisterFromServer() throws RemoteException {
+ mLocationManager.removeGpsMeasurementsListener(mListenerTransport);
}
private class ListenerTransport extends IGpsMeasurementsListener.Stub {
@Override
- public void onGpsMeasurementsReceived(final GpsMeasurementsEvent eventArgs) {
- Collection<GpsMeasurementsEvent.Listener> listeners;
- synchronized (mListeners) {
- listeners = new ArrayList<GpsMeasurementsEvent.Listener>(mListeners);
- }
+ public void onGpsMeasurementsReceived(final GpsMeasurementsEvent event) {
+ ListenerOperation<GpsMeasurementsEvent.Listener> operation =
+ new ListenerOperation<GpsMeasurementsEvent.Listener>() {
+ @Override
+ public void execute(GpsMeasurementsEvent.Listener listener) throws RemoteException {
+ listener.onGpsMeasurementsReceived(event);
+ }
+ };
- for (final GpsMeasurementsEvent.Listener listener : listeners) {
- listener.onGpsMeasurementsReceived(eventArgs);
- }
+ foreach(operation);
}
}
}
diff --git a/location/java/android/location/GpsNavigationMessage.java b/location/java/android/location/GpsNavigationMessage.java
new file mode 100644
index 000000000000..2eb4708164d7
--- /dev/null
+++ b/location/java/android/location/GpsNavigationMessage.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2014 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.location;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.security.InvalidParameterException;
+
+/**
+ * A class containing a GPS satellite Navigation Message.
+ *
+ * @hide
+ */
+public class GpsNavigationMessage implements Parcelable {
+ private static final String TAG = "GpsNavigationMessage";
+ private static final byte[] EMPTY_ARRAY = new byte[0];
+
+ // The following enumerations must be in sync with the values declared in gps.h
+
+ /**
+ * The type of the navigation message is not available or unknown.
+ */
+ public static final byte TYPE_UNKNOWN = 0;
+
+ /**
+ * The Navigation Message is of type L1 C/A.
+ */
+ public static final byte TYPE_L1CA = 1;
+
+ /**
+ * The Navigation Message is of type L1-CNAV.
+ */
+ public static final byte TYPE_L2CNAV = 2;
+
+ /**
+ * The Navigation Message is of type L5-CNAV.
+ */
+ public static final byte TYPE_L5CNAV = 3;
+
+ /**
+ * The Navigation Message is of type CNAV-2.
+ */
+ public static final byte TYPE_CNAV2 = 4;
+
+ // End enumerations in sync with gps.h
+
+ private byte mType;
+ private byte mPrn;
+ private short mMessageId;
+ private short mSubmessageId;
+ private byte[] mData;
+
+ GpsNavigationMessage() {
+ initialize();
+ }
+
+ /**
+ * Sets all contents to the values stored in the provided object.
+ */
+ public void set(GpsNavigationMessage navigationMessage) {
+ mType = navigationMessage.mType;
+ mPrn = navigationMessage.mPrn;
+ mMessageId = navigationMessage.mMessageId;
+ mSubmessageId = navigationMessage.mSubmessageId;
+ mData = navigationMessage.mData;
+ }
+
+ /**
+ * Resets all the contents to its original state.
+ */
+ public void reset() {
+ initialize();
+ }
+
+ /**
+ * Gets the type of the navigation message contained in the object.
+ */
+ public byte getType() {
+ return mType;
+ }
+
+ /**
+ * Sets the type of the navigation message.
+ */
+ public void setType(byte value) {
+ switch (value) {
+ case TYPE_UNKNOWN:
+ case TYPE_L1CA:
+ case TYPE_L2CNAV:
+ case TYPE_L5CNAV:
+ case TYPE_CNAV2:
+ mType = value;
+ break;
+ default:
+ Log.d(TAG, "Sanitizing invalid 'type': " + value);
+ mType = TYPE_UNKNOWN;
+ break;
+ }
+ }
+
+ /**
+ * Gets a string representation of the 'type'.
+ * For internal and logging use only.
+ */
+ private String getTypeString() {
+ switch (mType) {
+ case TYPE_UNKNOWN:
+ return "Unknown";
+ case TYPE_L1CA:
+ return "L1 C/A";
+ case TYPE_L2CNAV:
+ return "L2-CNAV";
+ case TYPE_L5CNAV:
+ return "L5-CNAV";
+ case TYPE_CNAV2:
+ return "CNAV-2";
+ default:
+ return "<Invalid>";
+ }
+ }
+
+ /**
+ * Gets the Pseudo-random number.
+ * Range: [1, 32].
+ */
+ public byte getPrn() {
+ return mPrn;
+ }
+
+ /**
+ * Sets the Pseud-random number.
+ */
+ public void setPrn(byte value) {
+ mPrn = value;
+ }
+
+ /**
+ * Gets the Message Identifier.
+ * It provides an index so the complete Navigation Message can be assembled. i.e. for L1 C/A
+ * subframe 4 and 5, this value corresponds to the 'frame id' of the navigation message.
+ * Subframe 1, 2, 3 does not contain a 'frame id' and this might be reported as -1.
+ */
+ public short getMessageId() {
+ return mMessageId;
+ }
+
+ /**
+ * Sets the Message Identifier.
+ */
+ public void setMessageId(short value) {
+ mMessageId = value;
+ }
+
+ /**
+ * Gets the Sub-message Identifier.
+ * If required by {@link #getType()}, this value contains a sub-index within the current message
+ * (or frame) that is being transmitted. i.e. for L1 C/A the sub-message identifier corresponds
+ * to the sub-frame Id of the navigation message.
+ */
+ public short getSubmessageId() {
+ return mSubmessageId;
+ }
+
+ /**
+ * Sets the Sub-message identifier.
+ */
+ public void setSubmessageId(short value) {
+ mSubmessageId = value;
+ }
+
+ /**
+ * Gets the data associated with the Navigation Message.
+ * The bytes (or words) specified using big endian format (MSB first).
+ */
+ @NonNull
+ public byte[] getData() {
+ return mData;
+ }
+
+ /**
+ * Sets the data associated with the Navigation Message.
+ */
+ public void setData(byte[] value) {
+ if (value == null) {
+ throw new InvalidParameterException("Data must be a non-null array");
+ }
+
+ mData = value;
+ }
+
+ public static final Creator<GpsNavigationMessage> CREATOR =
+ new Creator<GpsNavigationMessage>() {
+ @Override
+ public GpsNavigationMessage createFromParcel(Parcel parcel) {
+ GpsNavigationMessage navigationMessage = new GpsNavigationMessage();
+
+ navigationMessage.setType(parcel.readByte());
+ navigationMessage.setPrn(parcel.readByte());
+ navigationMessage.setMessageId((short) parcel.readInt());
+ navigationMessage.setSubmessageId((short) parcel.readInt());
+
+ int dataLength = parcel.readInt();
+ byte[] data = new byte[dataLength];
+ parcel.readByteArray(data);
+ navigationMessage.setData(data);
+
+ return navigationMessage;
+ }
+
+ @Override
+ public GpsNavigationMessage[] newArray(int size) {
+ return new GpsNavigationMessage[size];
+ }
+ };
+
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeByte(mType);
+ parcel.writeByte(mPrn);
+ parcel.writeInt(mMessageId);
+ parcel.writeInt(mSubmessageId);
+ parcel.writeInt(mData.length);
+ parcel.writeByteArray(mData);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ final String format = " %-15s = %s\n";
+ StringBuilder builder = new StringBuilder("GpsNavigationMessage:\n");
+
+ builder.append(String.format(format, "Type", getTypeString()));
+ builder.append(String.format(format, "Prn", mPrn));
+ builder.append(String.format(format, "MessageId", mMessageId));
+ builder.append(String.format(format, "SubmessageId", mSubmessageId));
+
+ builder.append(String.format(format, "Data", "{"));
+ String prefix = " ";
+ for(byte value : mData) {
+ builder.append(prefix);
+ builder.append(value);
+ prefix = ", ";
+ }
+ builder.append(" }");
+
+ return builder.toString();
+ }
+
+ private void initialize() {
+ mType = TYPE_UNKNOWN;
+ mPrn = 0;
+ mMessageId = -1;
+ mSubmessageId = -1;
+ mData = EMPTY_ARRAY;
+ }
+}
diff --git a/location/java/android/location/GpsNavigationMessageEvent.aidl b/location/java/android/location/GpsNavigationMessageEvent.aidl
new file mode 100644
index 000000000000..f84c2f72ca17
--- /dev/null
+++ b/location/java/android/location/GpsNavigationMessageEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014, 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.location;
+
+parcelable GpsNavigationMessageEvent;
diff --git a/location/java/android/location/GpsNavigationMessageEvent.java b/location/java/android/location/GpsNavigationMessageEvent.java
new file mode 100644
index 000000000000..50ffa75d3fa4
--- /dev/null
+++ b/location/java/android/location/GpsNavigationMessageEvent.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2014 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.location;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.security.InvalidParameterException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * A class implementing a container for data associated with a navigation message event.
+ * Events are delivered to registered instances of {@link Listener}.
+ *
+ * @hide
+ */
+public class GpsNavigationMessageEvent implements Parcelable {
+ private final GpsNavigationMessage mNavigationMessage;
+
+ /**
+ * Used for receiving GPS satellite Navigation Messages from the GPS engine.
+ * You can implement this interface and call
+ * {@link LocationManager#addGpsNavigationMessageListener}.
+ *
+ * @hide
+ */
+ public interface Listener {
+ void onGpsNavigationMessageReceived(GpsNavigationMessageEvent event);
+ }
+
+ public GpsNavigationMessageEvent(GpsNavigationMessage message) {
+ if (message == null) {
+ throw new InvalidParameterException("Parameter 'message' must not be null.");
+ }
+ mNavigationMessage = message;
+ }
+
+ @NonNull
+ public GpsNavigationMessage getNavigationMessage() {
+ return mNavigationMessage;
+ }
+
+ public static final Creator<GpsNavigationMessageEvent> CREATOR =
+ new Creator<GpsNavigationMessageEvent>() {
+ @Override
+ public GpsNavigationMessageEvent createFromParcel(Parcel in) {
+ ClassLoader classLoader = getClass().getClassLoader();
+ GpsNavigationMessage navigationMessage = in.readParcelable(classLoader);
+ return new GpsNavigationMessageEvent(navigationMessage);
+ }
+
+ @Override
+ public GpsNavigationMessageEvent[] newArray(int size) {
+ return new GpsNavigationMessageEvent[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeParcelable(mNavigationMessage, flags);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("[ GpsNavigationMessageEvent:\n\n");
+ builder.append(mNavigationMessage.toString());
+ builder.append("\n]");
+ return builder.toString();
+ }
+}
diff --git a/location/java/android/location/GpsNavigationMessageListenerTransport.java b/location/java/android/location/GpsNavigationMessageListenerTransport.java
new file mode 100644
index 000000000000..ec4812bca7c7
--- /dev/null
+++ b/location/java/android/location/GpsNavigationMessageListenerTransport.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 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.location;
+
+import android.content.Context;
+import android.os.RemoteException;
+
+/**
+ * A handler class to manage transport listeners for {@link GpsNavigationMessageEvent.Listener}.
+ *
+ * @hide
+ */
+class GpsNavigationMessageListenerTransport
+ extends LocalListenerHelper<GpsNavigationMessageEvent.Listener> {
+ private final Context mContext;
+ private final ILocationManager mLocationManager;
+
+ private final IGpsNavigationMessageListener mListenerTransport = new ListenerTransport();
+
+ public GpsNavigationMessageListenerTransport(
+ Context context,
+ ILocationManager locationManager) {
+ super("GpsNavigationMessageListenerTransport");
+ mContext = context;
+ mLocationManager = locationManager;
+ }
+
+ @Override
+ protected boolean registerWithServer() throws RemoteException {
+ return mLocationManager.addGpsNavigationMessageListener(
+ mListenerTransport,
+ mContext.getPackageName());
+ }
+
+ @Override
+ protected void unregisterFromServer() throws RemoteException {
+ mLocationManager.removeGpsNavigationMessageListener(mListenerTransport);
+ }
+
+ private class ListenerTransport extends IGpsNavigationMessageListener.Stub {
+ @Override
+ public void onGpsNavigationMessageReceived(final GpsNavigationMessageEvent event) {
+ ListenerOperation<GpsNavigationMessageEvent.Listener> operation =
+ new ListenerOperation<GpsNavigationMessageEvent.Listener>() {
+ @Override
+ public void execute(GpsNavigationMessageEvent.Listener listener)
+ throws RemoteException {
+ listener.onGpsNavigationMessageReceived(event);
+ }
+ };
+
+ foreach(operation);
+ }
+ }
+}
diff --git a/location/java/android/location/IGpsNavigationMessageListener.aidl b/location/java/android/location/IGpsNavigationMessageListener.aidl
new file mode 100644
index 000000000000..18603feb1967
--- /dev/null
+++ b/location/java/android/location/IGpsNavigationMessageListener.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2014, 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.location;
+
+import android.location.GpsNavigationMessageEvent;
+
+/**
+ * {@hide}
+ */
+oneway interface IGpsNavigationMessageListener {
+ void onGpsNavigationMessageReceived(in GpsNavigationMessageEvent event);
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index a1acaf12371c..150171028958 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -22,6 +22,7 @@ import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
import android.location.IGpsMeasurementsListener;
+import android.location.IGpsNavigationMessageListener;
import android.location.IGpsStatusListener;
import android.location.ILocationListener;
import android.location.Location;
@@ -63,6 +64,11 @@ interface ILocationManager
boolean addGpsMeasurementsListener(in IGpsMeasurementsListener listener, in String packageName);
boolean removeGpsMeasurementsListener(in IGpsMeasurementsListener listener);
+ boolean addGpsNavigationMessageListener(
+ in IGpsNavigationMessageListener listener,
+ in String packageName);
+ boolean removeGpsNavigationMessageListener(in IGpsNavigationMessageListener listener);
+
// --- deprecated ---
List<String> getAllProviders();
List<String> getProviders(in Criteria criteria, boolean enabledOnly);
diff --git a/location/java/android/location/LocalListenerHelper.java b/location/java/android/location/LocalListenerHelper.java
new file mode 100644
index 000000000000..1f3bf6792812
--- /dev/null
+++ b/location/java/android/location/LocalListenerHelper.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 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.location;
+
+import com.android.internal.util.Preconditions;
+
+import android.annotation.NonNull;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+
+/**
+ * A base handler class to manage transport and local listeners.
+ *
+ * @hide
+ */
+abstract class LocalListenerHelper<TListener> {
+ private final HashSet<TListener> mListeners = new HashSet<TListener>();
+ private final String mTag;
+
+ protected LocalListenerHelper(String name) {
+ Preconditions.checkNotNull(name);
+ mTag = name;
+ }
+
+ public boolean add(@NonNull TListener listener) {
+ Preconditions.checkNotNull(listener);
+
+ synchronized (mListeners) {
+ // we need to register with the service first, because we need to find out if the
+ // service will actually support the request before we attempt anything
+ if (mListeners.isEmpty()) {
+ boolean registeredWithService;
+ try {
+ registeredWithService = registerWithServer();
+ } catch (RemoteException e) {
+ Log.e(mTag, "Error handling first listener.", e);
+ return false;
+ }
+ if (!registeredWithService) {
+ Log.e(mTag, "Unable to register listener transport.");
+ return false;
+ }
+ }
+
+ if (mListeners.contains(listener)) {
+ return true;
+ }
+ mListeners.add(listener);
+ }
+ return true;
+ }
+
+ public void remove(@NonNull TListener listener) {
+ Preconditions.checkNotNull(listener);
+
+ synchronized (mListeners) {
+ boolean removed = mListeners.remove(listener);
+ boolean isLastRemoved = removed && mListeners.isEmpty();
+ if (isLastRemoved) {
+ try {
+ unregisterFromServer();
+ } catch (RemoteException e) {
+
+ }
+ }
+ }
+ }
+
+ protected abstract boolean registerWithServer() throws RemoteException;
+ protected abstract void unregisterFromServer() throws RemoteException;
+
+ protected interface ListenerOperation<TListener> {
+ void execute(TListener listener) throws RemoteException;
+ }
+
+ protected void foreach(ListenerOperation operation) {
+ Collection<TListener> listeners;
+ synchronized (mListeners) {
+ listeners = new ArrayList<TListener>(mListeners);
+ }
+
+ for (TListener listener : listeners) {
+ try {
+ operation.execute(listener);
+ } catch (RemoteException e) {
+ Log.e(mTag, "Error in monitored listener.", e);
+ // don't return, give a fair chance to all listeners to receive the event
+ }
+ }
+ }
+}
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index d6a8fb8eda05..082a158dbb2c 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -59,6 +59,7 @@ public class LocationManager {
private final Context mContext;
private final ILocationManager mService;
private final GpsMeasurementListenerTransport mGpsMeasurementListenerTransport;
+ private final GpsNavigationMessageListenerTransport mGpsNavigationMessageListenerTransport;
private final HashMap<GpsStatus.Listener, GpsStatusListenerTransport> mGpsStatusListeners =
new HashMap<GpsStatus.Listener, GpsStatusListenerTransport>();
private final HashMap<GpsStatus.NmeaListener, GpsStatusListenerTransport> mNmeaListeners =
@@ -310,6 +311,8 @@ public class LocationManager {
mService = service;
mContext = context;
mGpsMeasurementListenerTransport = new GpsMeasurementListenerTransport(mContext, mService);
+ mGpsNavigationMessageListenerTransport =
+ new GpsNavigationMessageListenerTransport(mContext, mService);
}
private LocationProvider createProvider(String name, ProviderProperties properties) {
@@ -1573,7 +1576,7 @@ public class LocationManager {
/**
* Adds a GPS Measurement listener.
*
- * @param listener a {@link android.location.GpsMeasurementsEvent.Listener} object to register.
+ * @param listener a {@link GpsMeasurementsEvent.Listener} object to register.
* @return {@code true} if the listener was successfully registered, {@code false} otherwise.
*
* @hide
@@ -1593,6 +1596,30 @@ public class LocationManager {
mGpsMeasurementListenerTransport.remove(listener);
}
+ /**
+ * Adds a GPS Navigation Message listener.
+ *
+ * @param listener a {@link GpsNavigationMessageEvent.Listener} object to register.
+ * @return {@code true} if the listener was successfully registered, {@code false} otherwise.
+ *
+ * @hide
+ */
+ public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
+ return mGpsNavigationMessageListenerTransport.add(listener);
+ }
+
+ /**
+ * Removes a GPS Navigation Message listener.
+ *
+ * @param listener a {@link GpsNavigationMessageEvent.Listener} object to remove.
+ *
+ * @hide
+ */
+ public void removeGpsNavigationMessageListener(
+ GpsNavigationMessageEvent.Listener listener) {
+ mGpsNavigationMessageListenerTransport.remove(listener);
+ }
+
/**
* Retrieves information about the current status of the GPS engine.
* This should only be called from the {@link GpsStatus.Listener#onGpsStatusChanged}
diff --git a/media/java/android/media/RemoteController.java b/media/java/android/media/RemoteController.java
index 3c09782b046d..75a89528374d 100644
--- a/media/java/android/media/RemoteController.java
+++ b/media/java/android/media/RemoteController.java
@@ -395,12 +395,6 @@ import java.util.List;
mArtworkWidth = -1;
mArtworkHeight = -1;
}
- if (mIsRegistered) {
- mAudioManager.remoteControlDisplayUsesBitmapSize(mRcd,
- mArtworkWidth, mArtworkHeight);
- } // else new values have been stored, and will be read by AudioManager with
- // RemoteController.getArtworkSize() when AudioManager.registerRemoteController()
- // is called.
}
return true;
}
@@ -1042,7 +1036,8 @@ import java.util.List;
boolean canRate = mCurrentSession != null
&& mCurrentSession.getRatingType() != Rating.RATING_NONE;
long editableKeys = canRate ? MediaMetadataEditor.RATING_KEY_BY_USER : 0;
- Bundle legacyMetadata = MediaSessionLegacyHelper.getOldMetadata(metadata);
+ Bundle legacyMetadata = MediaSessionLegacyHelper.getOldMetadata(metadata,
+ mArtworkWidth, mArtworkHeight);
mMetadataEditor = new MetadataEditor(legacyMetadata, editableKeys);
metadataEditor = mMetadataEditor;
}
diff --git a/media/java/android/media/browse/MediaBrowserItem.java b/media/java/android/media/browse/MediaBrowserItem.java
index 38e765ffb03a..d0a03426f444 100644
--- a/media/java/android/media/browse/MediaBrowserItem.java
+++ b/media/java/android/media/browse/MediaBrowserItem.java
@@ -16,6 +16,7 @@
package android.media.browse;
+import android.annotation.DrawableRes;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -32,11 +33,11 @@ import java.lang.annotation.RetentionPolicy;
*/
public final class MediaBrowserItem implements Parcelable {
private final Uri mUri;
- private final Uri mIconUri;
- private final int mIconResId;
private final int mFlags;
private final CharSequence mTitle;
private final CharSequence mSummary;
+ private final Uri mIconUri;
+ private final int mIconResourceId;
private final Bundle mExtras;
/** @hide */
@@ -61,8 +62,8 @@ public final class MediaBrowserItem implements Parcelable {
/**
* Initialize a MediaBrowserItem object.
*/
- private MediaBrowserItem(@NonNull Uri uri, @Nullable Uri iconUri, int iconResId, int flags,
- @NonNull CharSequence title, CharSequence summary, Bundle extras) {
+ private MediaBrowserItem(@NonNull Uri uri, int flags, @NonNull CharSequence title,
+ CharSequence summary, @Nullable Uri iconUri, int iconResourceId, Bundle extras) {
if (uri == null) {
throw new IllegalArgumentException("uri can not be null");
}
@@ -70,11 +71,11 @@ public final class MediaBrowserItem implements Parcelable {
throw new IllegalArgumentException("title can not be null");
}
mUri = uri;
- mIconUri = iconUri;
- mIconResId = iconResId;
mFlags = flags;
mTitle = title;
mSummary = summary;
+ mIconUri = iconUri;
+ mIconResourceId = iconResourceId;
mExtras = extras;
}
@@ -83,8 +84,6 @@ public final class MediaBrowserItem implements Parcelable {
*/
private MediaBrowserItem(Parcel in) {
mUri = Uri.CREATOR.createFromParcel(in);
- mIconUri = Uri.CREATOR.createFromParcel(in);
- mIconResId = in.readInt();
mFlags = in.readInt();
mTitle = in.readCharSequence();
if (in.readInt() != 0) {
@@ -93,6 +92,12 @@ public final class MediaBrowserItem implements Parcelable {
mSummary = null;
}
if (in.readInt() != 0) {
+ mIconUri = Uri.CREATOR.createFromParcel(in);
+ } else {
+ mIconUri = null;
+ }
+ mIconResourceId = in.readInt();
+ if (in.readInt() != 0) {
mExtras = Bundle.CREATOR.createFromParcel(in);
} else {
mExtras = null;
@@ -107,8 +112,6 @@ public final class MediaBrowserItem implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
mUri.writeToParcel(out, flags);
- mIconUri.writeToParcel(out, flags);
- out.writeInt(mIconResId);
out.writeInt(mFlags);
out.writeCharSequence(mTitle);
if (mSummary != null) {
@@ -117,6 +120,13 @@ public final class MediaBrowserItem implements Parcelable {
} else {
out.writeInt(0);
}
+ if (mIconUri != null) {
+ out.writeInt(1);
+ mIconUri.writeToParcel(out, flags);
+ } else {
+ out.writeInt(0);
+ }
+ out.writeInt(mIconResourceId);
if (mExtras != null) {
out.writeInt(1);
mExtras.writeToParcel(out, flags);
@@ -127,16 +137,16 @@ public final class MediaBrowserItem implements Parcelable {
public static final Parcelable.Creator<MediaBrowserItem> CREATOR =
new Parcelable.Creator<MediaBrowserItem>() {
- @Override
- public MediaBrowserItem createFromParcel(Parcel in) {
- return new MediaBrowserItem(in);
- }
+ @Override
+ public MediaBrowserItem createFromParcel(Parcel in) {
+ return new MediaBrowserItem(in);
+ }
- @Override
- public MediaBrowserItem[] newArray(int size) {
- return new MediaBrowserItem[size];
- }
- };
+ @Override
+ public MediaBrowserItem[] newArray(int size) {
+ return new MediaBrowserItem[size];
+ }
+ };
/**
* Gets the Uri of the item.
@@ -146,20 +156,6 @@ public final class MediaBrowserItem implements Parcelable {
}
/**
- * Gets the Uri of the icon.
- */
- public @Nullable Uri getIconUri() {
- return mIconUri;
- }
-
- /**
- * Gets the resource id of the icon.
- */
- public int getIconResId() {
- return mIconResId;
- }
-
- /**
* Gets the flags of the item.
*/
public @Flags int getFlags() {
@@ -203,6 +199,20 @@ public final class MediaBrowserItem implements Parcelable {
}
/**
+ * Gets the Uri of the icon.
+ */
+ public @Nullable Uri getIconUri() {
+ return mIconUri;
+ }
+
+ /**
+ * Gets the resource id of the icon.
+ */
+ public @DrawableRes int getIconResourceId() {
+ return mIconResourceId;
+ }
+
+ /**
* Gets additional service-specified extras about the
* item or its content, or null if none.
*/
@@ -217,9 +227,9 @@ public final class MediaBrowserItem implements Parcelable {
private final Uri mUri;
private final int mFlags;
private final CharSequence mTitle;
- private Uri mIconUri;
- private int mIconResId;
private CharSequence mSummary;
+ private Uri mIconUri;
+ private int mIconResourceId;
private Bundle mExtras;
/**
@@ -238,10 +248,18 @@ public final class MediaBrowserItem implements Parcelable {
}
/**
+ * Sets summary of the item, or null if none.
+ */
+ public @NonNull Builder setSummary(@Nullable CharSequence summary) {
+ mSummary = summary;
+ return this;
+ }
+
+ /**
* Sets the uri of the icon.
* <p>
- * If both {@link #setIconUri(Uri)} and {@link #setIconResId(int)} are called,
- * the resource id will be used to load the icon.
+ * Either {@link #setIconUri(Uri)} or {@link #setIconResourceId(int)} should be called.
+ * If both are specified, the resource id will be used to load the icon.
* </p>
*/
public @NonNull Builder setIconUri(@Nullable Uri iconUri) {
@@ -251,35 +269,31 @@ public final class MediaBrowserItem implements Parcelable {
/**
* Sets the resource id of the icon.
+ * <p>
+ * Either {@link #setIconUri(Uri)} or {@link #setIconResourceId(int)} should be specified.
+ * If both are specified, the resource id will be used to load the icon.
+ * </p>
*/
- public @NonNull Builder setIconResId(int resId) {
- mIconResId = resId;
+ public @NonNull Builder setIconResourceId(@DrawableRes int ResourceId) {
+ mIconResourceId = ResourceId;
return this;
}
/**
- * Sets summary of the item, or null if none.
+ * Sets additional service-specified extras about the
+ * item or its content.
*/
- public @NonNull Builder setSummary(@Nullable CharSequence summary) {
- mSummary = summary;
- return this;
- }
-
- /**
- * Sets additional service-specified extras about the
- * item or its content, or null if none.
- */
public @NonNull Builder setExtras(@Nullable Bundle extras) {
mExtras = extras;
return this;
}
/**
- * Builds the item.
- */
+ * Builds the item.
+ */
public @NonNull MediaBrowserItem build() {
- return new MediaBrowserItem(mUri, mIconUri, mIconResId,
- mFlags, mTitle, mSummary, mExtras);
+ return new MediaBrowserItem(mUri, mFlags, mTitle, mSummary, mIconUri,
+ mIconResourceId, mExtras);
}
}
}
diff --git a/media/java/android/media/browse/MediaBrowserService.java b/media/java/android/media/browse/MediaBrowserService.java
index 57befe7acca2..95a133f8877f 100644
--- a/media/java/android/media/browse/MediaBrowserService.java
+++ b/media/java/android/media/browse/MediaBrowserService.java
@@ -256,7 +256,7 @@ public abstract class MediaBrowserService extends Service {
* for browsing, or null if none. The contents of this bundle may affect
* the information returned when browsing.
*/
- protected abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
+ public abstract @Nullable BrowserRoot onGetRoot(@NonNull String clientPackageName,
int clientUid, @Nullable Bundle rootHints);
/**
@@ -266,7 +266,7 @@ public abstract class MediaBrowserService extends Service {
* children are to be queried.
* @return The list of children, or null if the uri is invalid.
*/
- protected abstract @Nullable List<MediaBrowserItem> onLoadChildren(@NonNull Uri parentUri);
+ public abstract @Nullable List<MediaBrowserItem> onLoadChildren(@NonNull Uri parentUri);
/**
* Called to get the thumbnail of a particular media item.
@@ -278,7 +278,7 @@ public abstract class MediaBrowserService extends Service {
* @return The file descriptor of the thumbnail, which may then be loaded
* using a bitmap factory, or null if the item does not have a thumbnail.
*/
- protected abstract @Nullable Bitmap onGetThumbnail(@NonNull Uri uri, int width, int height);
+ public abstract @Nullable Bitmap onGetThumbnail(@NonNull Uri uri, int width, int height);
/**
* Call to set the media session.
@@ -311,20 +311,21 @@ public abstract class MediaBrowserService extends Service {
* @param parentUri The uri of the parent media item whose
* children changed.
*/
- public void notifyChildrenChanged(@NonNull Uri parentUri) {
+ public void notifyChildrenChanged(@NonNull final Uri parentUri) {
if (parentUri == null) {
throw new IllegalArgumentException("parentUri cannot be null in notifyChildrenChanged");
}
- for (IBinder binder : mConnections.keySet()) {
- ConnectionRecord connection = mConnections.get(binder);
- Set<Uri> uris = connection.subscriptions;
- for (Uri uri : uris) {
- if (uri.equals(parentUri)) {
- performLoadChildren(uri, connection);
- break;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ for (IBinder binder : mConnections.keySet()) {
+ ConnectionRecord connection = mConnections.get(binder);
+ if (connection.subscriptions.contains(parentUri)) {
+ performLoadChildren(parentUri, connection);
+ }
}
}
- }
+ });
}
/**
@@ -380,9 +381,19 @@ public abstract class MediaBrowserService extends Service {
}
}
- public static class BrowserRoot {
+ /**
+ * Contains information that the browser service needs to send to the client
+ * when first connected.
+ */
+ public static final class BrowserRoot {
final private Uri mUri;
final private Bundle mExtras;
+
+ /**
+ * Constructs a browser root.
+ * @param uri The root Uri for browsing.
+ * @param extras Any extras about the browser service.
+ */
public BrowserRoot(@NonNull Uri uri, @Nullable Bundle extras) {
if (uri == null) {
throw new IllegalArgumentException("The root uri in BrowserRoot cannot be null. " +
@@ -392,11 +403,17 @@ public abstract class MediaBrowserService extends Service {
mExtras = extras;
}
- Uri getRootUri() {
+ /**
+ * Gets the root uri for browsing.
+ */
+ public Uri getRootUri() {
return mUri;
}
- Bundle getExtras() {
+ /**
+ * Gets any extras about the brwoser service.
+ */
+ public Bundle getExtras() {
return mExtras;
}
}
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
index da1a6edbe7e4..a6963cfe98af 100644
--- a/media/java/android/media/session/MediaSessionLegacyHelper.java
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -21,6 +21,10 @@ import android.app.PendingIntent.CanceledException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
import android.media.AudioManager;
import android.media.MediaMetadata;
import android.media.MediaMetadataEditor;
@@ -73,19 +77,23 @@ public class MediaSessionLegacyHelper {
return sInstance;
}
- public static Bundle getOldMetadata(MediaMetadata metadata) {
+ public static Bundle getOldMetadata(MediaMetadata metadata, int artworkWidth,
+ int artworkHeight) {
+ boolean includeArtwork = artworkWidth != -1 && artworkHeight != -1;
Bundle oldMetadata = new Bundle();
if (metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM)) {
oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_ALBUM),
metadata.getString(MediaMetadata.METADATA_KEY_ALBUM));
}
- if (metadata.containsKey(MediaMetadata.METADATA_KEY_ART)) {
+ if (includeArtwork && metadata.containsKey(MediaMetadata.METADATA_KEY_ART)) {
+ Bitmap art = metadata.getBitmap(MediaMetadata.METADATA_KEY_ART);
oldMetadata.putParcelable(String.valueOf(MediaMetadataEditor.BITMAP_KEY_ARTWORK),
- metadata.getBitmap(MediaMetadata.METADATA_KEY_ART));
- } else if (metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM_ART)) {
+ scaleBitmapIfTooBig(art, artworkWidth, artworkHeight));
+ } else if (includeArtwork && metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM_ART)) {
// Fall back to album art if the track art wasn't available
+ Bitmap art = metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART);
oldMetadata.putParcelable(String.valueOf(MediaMetadataEditor.BITMAP_KEY_ARTWORK),
- metadata.getBitmap(MediaMetadata.METADATA_KEY_ALBUM_ART));
+ scaleBitmapIfTooBig(art, artworkWidth, artworkHeight));
}
if (metadata.containsKey(MediaMetadata.METADATA_KEY_ALBUM_ARTIST)) {
oldMetadata.putString(String.valueOf(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST),
@@ -322,6 +330,41 @@ public class MediaSessionLegacyHelper {
}
}
+ /**
+ * Scale a bitmap to fit the smallest dimension by uniformly scaling the
+ * incoming bitmap. If the bitmap fits, then do nothing and return the
+ * original.
+ *
+ * @param bitmap
+ * @param maxWidth
+ * @param maxHeight
+ * @return
+ */
+ private static Bitmap scaleBitmapIfTooBig(Bitmap bitmap, int maxWidth, int maxHeight) {
+ if (bitmap != null) {
+ final int width = bitmap.getWidth();
+ final int height = bitmap.getHeight();
+ if (width > maxWidth || height > maxHeight) {
+ float scale = Math.min((float) maxWidth / width, (float) maxHeight / height);
+ int newWidth = Math.round(scale * width);
+ int newHeight = Math.round(scale * height);
+ Bitmap.Config newConfig = bitmap.getConfig();
+ if (newConfig == null) {
+ newConfig = Bitmap.Config.ARGB_8888;
+ }
+ Bitmap outBitmap = Bitmap.createBitmap(newWidth, newHeight, newConfig);
+ Canvas canvas = new Canvas(outBitmap);
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setFilterBitmap(true);
+ canvas.drawBitmap(bitmap, null,
+ new RectF(0, 0, outBitmap.getWidth(), outBitmap.getHeight()), paint);
+ bitmap = outBitmap;
+ }
+ }
+ return bitmap;
+ }
+
private SessionHolder getHolder(PendingIntent pi, boolean createIfMissing) {
SessionHolder holder = mSessions.get(pi);
if (holder == null && createIfMissing) {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 686f86547cc1..5ce35792b384 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -323,6 +323,19 @@
</intent-filter>
</activity>
+ <activity
+ android:name=".settings.BrightnessDialog"
+ android:label="@string/quick_settings_brightness_dialog_title"
+ android:theme="@android:style/Theme.DeviceDefault.Light.Dialog"
+ android:finishOnCloseSystemDialogs="true"
+ android:launchMode="singleInstance"
+ android:excludeFromRecents="true"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.SHOW_BRIGHTNESS_DIALOG" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ </activity>
<!-- I dream of notifications -->
<service
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 85668de3c854..93c55387812c 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -67,8 +67,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/recents_task_view_lock_to_app_button_height"
android:layout_gravity="center_horizontal|bottom"
- android:background="@drawable/recents_lock_to_task_button_bg"
- android:visibility="invisible">
+ android:background="@drawable/recents_lock_to_task_button_bg">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 8b11ef173993..230f4af0d4c0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -159,8 +159,14 @@
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">false</bool>
+ <!-- Doze: does this device support STATE_DOZE and STATE_DOZE_SUSPEND? -->
+ <bool name="doze_display_state_supported">false</bool>
+
<!-- Doze: should the significant motion sensor be used as a tease signal? -->
- <bool name="doze_tease_on_significant_motion">true</bool>
+ <bool name="doze_tease_on_significant_motion">false</bool>
+
+ <!-- Doze: maximum brightness to use when teasing -->
+ <integer name="doze_tease_brightness">80</integer>
<!-- Volume: time to delay dismissing the volume panel after a click is performed -->
<integer name="volume_panel_dismiss_delay">200</integer>
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 630ba133183b..b3f90d7027bd 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -46,8 +46,7 @@ public class SystemUIApplication extends Application {
com.android.systemui.statusbar.SystemBars.class,
com.android.systemui.usb.StorageNotification.class,
com.android.systemui.power.PowerUI.class,
- com.android.systemui.media.RingtonePlayer.class,
- com.android.systemui.settings.SettingsUI.class,
+ com.android.systemui.media.RingtonePlayer.class
};
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 269b4ed495e6..333b8b483142 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -16,20 +16,27 @@
package com.android.systemui.doze;
+import static android.os.PowerManager.BRIGHTNESS_OFF;
+import static android.os.PowerManager.BRIGHTNESS_ON;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
+import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemProperties;
import android.os.Vibrator;
import android.service.dreams.DozeHardware;
import android.service.dreams.DreamService;
import android.util.Log;
+import android.util.MathUtils;
+import android.view.Display;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
@@ -38,12 +45,14 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
public class DozeService extends DreamService {
- private static final boolean DEBUG = false;
+ private static final String TAG = "DozeService";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String TEASE_ACTION = "com.android.systemui.doze.tease";
- private final String mTag = String.format("DozeService.%08x", hashCode());
+ private final String mTag = String.format(TAG + ".%08x", hashCode());
private final Context mContext = this;
+ private final Handler mHandler = new Handler();
private Host mHost;
private DozeHardware mDozeHardware;
@@ -51,10 +60,13 @@ public class DozeService extends DreamService {
private Sensor mSigMotionSensor;
private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;
+ private int mMaxBrightness;
private boolean mDreaming;
private boolean mTeaseReceiverRegistered;
private boolean mSigMotionConfigured;
private boolean mSigMotionEnabled;
+ private boolean mDisplayStateSupported;
+ private int mDisplayStateWhenOn;
public DozeService() {
if (DEBUG) Log.d(mTag, "new DozeService()");
@@ -70,6 +82,8 @@ public class DozeService extends DreamService {
pw.print(" mSigMotionSensor: "); pw.println(mSigMotionSensor);
pw.print(" mSigMotionConfigured: "); pw.println(mSigMotionConfigured);
pw.print(" mSigMotionEnabled: "); pw.println(mSigMotionEnabled);
+ pw.print(" mMaxBrightness: "); pw.println(mMaxBrightness);
+ pw.print(" mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
}
@Override
@@ -88,8 +102,16 @@ public class DozeService extends DreamService {
mSigMotionSensor = mSensors.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
+ final Resources res = mContext.getResources();
mSigMotionConfigured = SystemProperties.getBoolean("doze.tease.sigmotion",
- mContext.getResources().getBoolean(R.bool.doze_tease_on_significant_motion));
+ res.getBoolean(R.bool.doze_tease_on_significant_motion));
+ mDisplayStateSupported = SystemProperties.getBoolean("doze.display.supported",
+ res.getBoolean(R.bool.doze_display_state_supported));
+ mMaxBrightness = MathUtils.constrain(res.getInteger(R.integer.doze_tease_brightness),
+ BRIGHTNESS_OFF, BRIGHTNESS_ON);
+
+ mDisplayStateWhenOn = mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON;
+ setDozeScreenState(mDisplayStateWhenOn);
}
@Override
@@ -112,9 +134,18 @@ public class DozeService extends DreamService {
public void stayAwake(long millis) {
if (mDreaming && millis > 0) {
mWakeLock.acquire(millis);
+ setDozeScreenState(mDisplayStateWhenOn);
+ setDozeScreenBrightness(mMaxBrightness);
+ rescheduleOff(millis);
}
}
+ private void rescheduleOff(long millis) {
+ if (DEBUG) Log.d(TAG, "rescheduleOff millis=" + millis);
+ mHandler.removeCallbacks(mDisplayOff);
+ mHandler.postDelayed(mDisplayOff, millis);
+ }
+
public void startDozing() {
if (DEBUG) Log.d(mTag, "startDozing mDreaming=" + mDreaming);
if (!mDreaming) {
@@ -225,6 +256,15 @@ public class DozeService extends DreamService {
return sb.append(']').toString();
}
+ private final Runnable mDisplayOff = new Runnable() {
+ @Override
+ public void run() {
+ if (DEBUG) Log.d(TAG, "Display off");
+ setDozeScreenState(Display.STATE_OFF);
+ setDozeScreenBrightness(PowerManager.BRIGHTNESS_DEFAULT);
+ }
+ };
+
private final TriggerEventListener mSigMotionListener = new TriggerEventListener() {
@Override
public void onTrigger(TriggerEvent event) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7d69b9469bee..18dad3a81815 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -431,6 +431,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
super.onNewIntent(intent);
setIntent(intent);
+ // Reinitialize the configuration
+ RecentsConfiguration.reinitialize(this, RecentsTaskLoader.getInstance().getSystemServicesProxy());
+
// Clear any debug rects
if (mDebugOverlay != null) {
mDebugOverlay.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 55711cf0ad70..bffc23047a17 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -305,6 +305,11 @@ public class RecentsConfiguration {
(!transposeRecentsLayoutWithOrientation || !isLandscape);
}
+ /** Returns whether the current layout is horizontal. */
+ public boolean hasHorizontalLayout() {
+ return isLandscape && transposeRecentsLayoutWithOrientation;
+ }
+
/**
* Returns the task stack bounds in the current orientation. These bounds do not account for
* the system insets.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 9076818cec8e..34f73c6bb516 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents.views;
import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.graphics.Outline;
import android.graphics.Rect;
import android.view.View;
@@ -34,6 +35,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
int mCornerRadius;
ObjectAnimator mClipTopAnimator;
+ ObjectAnimator mClipRightAnimator;
ObjectAnimator mClipBottomAnimator;
public AnimateableViewBounds(View source, int cornerRadius) {
@@ -42,6 +44,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
mCornerRadius = cornerRadius;
mSourceView.setClipToOutline(true);
setClipTop(getClipTop());
+ setClipRight(getClipRight());
setClipBottom(getClipBottom());
setOutlineClipBottom(getOutlineClipBottom());
}
@@ -56,7 +59,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
}
/** Animates the top clip. */
- void animateClipTop(int top, int duration) {
+ void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) {
if (mClipTopAnimator != null) {
mClipTopAnimator.removeAllListeners();
mClipTopAnimator.cancel();
@@ -64,6 +67,9 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top);
mClipTopAnimator.setDuration(duration);
mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ if (updateListener != null) {
+ mClipTopAnimator.addUpdateListener(updateListener);
+ }
mClipTopAnimator.start();
}
@@ -80,16 +86,41 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
return mClipRect.top;
}
+ /** Animates the right clip. */
+ void animateClipRight(int right, int duration) {
+ if (mClipRightAnimator != null) {
+ mClipRightAnimator.removeAllListeners();
+ mClipRightAnimator.cancel();
+ }
+ mClipRightAnimator = ObjectAnimator.ofInt(this, "clipRight", right);
+ mClipRightAnimator.setDuration(duration);
+ mClipRightAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mClipRightAnimator.start();
+ }
+
+ /** Sets the right clip. */
+ public void setClipRight(int right) {
+ if (right != mClipRect.right) {
+ mClipRect.right = right;
+ mSourceView.invalidateOutline();
+ }
+ }
+
+ /** Returns the right clip. */
+ public int getClipRight() {
+ return mClipRect.right;
+ }
+
/** Animates the bottom clip. */
void animateClipBottom(int bottom, int duration) {
- if (mClipTopAnimator != null) {
- mClipTopAnimator.removeAllListeners();
- mClipTopAnimator.cancel();
+ if (mClipBottomAnimator != null) {
+ mClipBottomAnimator.removeAllListeners();
+ mClipBottomAnimator.cancel();
}
- mClipTopAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
- mClipTopAnimator.setDuration(duration);
- mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mClipTopAnimator.start();
+ mClipBottomAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
+ mClipBottomAnimator.setDuration(duration);
+ mClipBottomAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+ mClipBottomAnimator.start();
}
/** Sets the bottom clip. */
@@ -105,6 +136,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
return mClipRect.bottom;
}
+ /** Sets the outline bottom clip. */
public void setOutlineClipBottom(int bottom) {
if (bottom != mOutlineClipRect.bottom) {
mOutlineClipRect.bottom = bottom;
@@ -112,6 +144,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
}
}
+ /** Gets the outline bottom clip. */
public int getOutlineClipBottom() {
return mOutlineClipRect.bottom;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
index 95af1c951baa..881bbcfceebe 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
@@ -16,12 +16,9 @@
package com.android.systemui.recents.views;
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
-import android.view.View;
import android.widget.FrameLayout;
import com.android.systemui.recents.RecentsConfiguration;
@@ -82,9 +79,6 @@ public class TaskFooterView extends FrameLayout {
void animateFooterVisibility(final boolean visible, int duration) {
// Return early if there is no footer
if (mMaxFooterHeight <= 0) return;
- // Return early if we are already in the final state
- if (!visible && getVisibility() != View.VISIBLE) return;
- if (visible && getVisibility() == View.VISIBLE) return;
// Cancel the previous animation
if (mFooterAnimator != null) {
@@ -93,25 +87,12 @@ public class TaskFooterView extends FrameLayout {
}
int finalHeight = visible ? mMaxFooterHeight : 0;
if (duration > 0) {
- // Make the view visible for the animation
- if (visible && getVisibility() != View.VISIBLE) {
- setVisibility(View.VISIBLE);
- }
mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", finalHeight);
mFooterAnimator.setDuration(duration);
mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
- mFooterAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- if (!visible) {
- setVisibility(View.INVISIBLE);
- }
- }
- });
mFooterAnimator.start();
} else {
setFooterHeight(finalHeight);
- setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index f135e320b5c3..b501f7e70e6d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -83,7 +83,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int mFocusedTaskIndex = -1;
OverScroller mScroller;
ObjectAnimator mScrollAnimator;
- boolean mEnableStackClipping = true;
// Optimizations
ReferenceCountedTrigger mHwLayersTrigger;
@@ -93,8 +92,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
boolean mStartEnterAnimationRequestedAfterLayout;
ViewAnimation.TaskViewEnterContext mStartEnterAnimationContext;
int[] mTmpVisibleRange = new int[2];
- Rect mTmpRect = new Rect();
- Rect mTmpRect2 = new Rect();
TaskViewTransform mTmpTransform = new TaskViewTransform();
HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<Task, TaskView>();
LayoutInflater mInflater;
@@ -189,7 +186,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int stackScroll,
int[] visibleRangeOut,
boolean boundTranslationsToRect) {
- // XXX: We should be intelligent about wheee to look for the visible stack range using the
+ // XXX: We should be intelligent about where to look for the visible stack range using the
// current stack scroll.
// XXX: We should log extra cases like the ones below where we don't expect to hit very often
// XXX: Print out approximately how many indices we have to go through to find the first visible transform
@@ -199,8 +196,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int frontMostVisibleIndex = -1;
int backMostVisibleIndex = -1;
-
-
// We can reuse the task transforms where possible to reduce object allocation
if (taskTransformCount < taskCount) {
// If there are less transforms than tasks, then add as many transforms as necessary
@@ -290,6 +285,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
+
if (mStackViewsAnimationDuration > 0) {
// For items in the list, put them in start animating them from the
// approriate ends of the list where they are expected to appear
@@ -319,7 +315,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/** Updates the clip for each of the task views. */
void clipTaskViews() {
// Update the clip on each task child
- if (Constants.DebugFlags.App.EnableTaskStackClipping && mEnableStackClipping) {
+ if (Constants.DebugFlags.App.EnableTaskStackClipping) {
int childCount = getChildCount();
for (int i = 0; i < childCount - 1; i++) {
TaskView tv = (TaskView) getChildAt(i);
@@ -341,12 +337,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// stacked and we can make assumptions about the visibility of the this
// task relative to the ones in front of it.
if (nextTv != null) {
- // We calculate the bottom clip independent of the footer (since we animate
- // that)
- int scaledMaxFooterHeight = (int) (tv.getMaxFooterHeight() * tv.getScaleX());
- tv.getHitRect(mTmpRect);
- nextTv.getHitRect(mTmpRect2);
- clipBottom = (mTmpRect.bottom - scaledMaxFooterHeight - mTmpRect2.top);
+ // We can reuse the current task transforms to find the task rects
+ TaskViewTransform transform = mCurrentTaskTransforms.get(mStack.indexOfTask(tv.getTask()));
+ TaskViewTransform nextTransform = mCurrentTaskTransforms.get(mStack.indexOfTask(nextTv.getTask()));
+ clipBottom = transform.rect.bottom - nextTransform.rect.top - 200;
}
}
tv.getViewBounds().setClipBottom(clipBottom);
@@ -359,18 +353,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
- /** Enables/Disables clipping of the tasks in the stack. */
- void setStackClippingEnabled(boolean stackClippingEnabled) {
- if (!stackClippingEnabled) {
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- tv.getViewBounds().setClipBottom(0);
- }
- }
- mEnableStackClipping = stackClippingEnabled;
- }
-
/** The stack insets to apply to the stack contents */
public void setStackInsetRect(Rect r) {
mTaskStackBounds.set(r);
@@ -634,18 +616,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
setStackScrollToInitialState();
requestSynchronizeStackViewsWithModel();
synchronizeStackViewsWithModel();
-
- // Find the first task and mark it as full screen
- if (mConfig.launchedFromAppWithScreenshot) {
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- if (tv.getTask().isLaunchTarget) {
- tv.setIsFullScreen(true);
- break;
- }
- }
- }
}
// Measure each of the TaskViews
@@ -925,6 +895,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public void prepareViewToLeavePool(TaskView tv, Task task, boolean isNewView) {
// Rebind the task and request that this task's data be filled into the TaskView
tv.onTaskBound(task);
+
+ // Mark the launch task as fullscreen
+ if (Constants.DebugFlags.App.EnableScreenshotAppTransition && mAwaitingFirstLayout) {
+ if (task.isLaunchTarget) {
+ tv.setIsFullScreen(true);
+ }
+ }
+
+ // Load the task data
RecentsTaskLoader.getInstance().loadTaskData(task);
// Sanity check, the task view should always be clipping against the stack at this point,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 7f94a0a29dac..0fd4e8642955 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -82,7 +82,7 @@ public class TaskStackViewLayoutAlgorithm {
// Compute the min and max scroll values
int numTasks = Math.max(1, tasks.size());
int taskHeight = mTaskRect.height();
- int stackHeight = mStackRect.height();
+ int stackHeight = mStackRectSansPeek.height();
if (numTasks <= 1) {
// If there is only one task, then center the task in the stack rect (sans peek)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index b83f9cc26546..b1c35f32196a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -263,7 +263,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
- // XXX: Make this animation a function of the velocity AND distance
int overscrollRange = (int) (Math.min(1f,
Math.abs((float) velocity / mMaximumVelocity)) *
Constants.Values.TaskStackView.TaskStackOverscrollRange);
@@ -277,7 +276,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
mSv.invalidate(mSv.mStackAlgorithm.mStackRect);
} else if (mSv.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
mSv.animateBoundScroll();
}
@@ -303,7 +301,6 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
case MotionEvent.ACTION_CANCEL: {
if (mSv.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
- // XXX: Make this animation a function of the velocity OR distance
mSv.animateBoundScroll();
}
mActivePointerId = INACTIVE_POINTER_ID;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 259706bd51ec..1b5ad6ee5828 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
@@ -60,7 +59,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
boolean mTaskDataLoaded;
boolean mIsFocused;
boolean mIsFullScreenView;
- boolean mIsStub;
boolean mClipViewInStack;
AnimateableViewBounds mViewBounds;
Paint mLayerPaint = new Paint();
@@ -123,7 +121,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
mFooterView = (TaskFooterView) findViewById(R.id.lock_to_app);
- mFooterView.setCallbacks(this);
+ if (mConfig.lockToAppEnabled) {
+ mFooterView.setCallbacks(this);
+ } else {
+ mFooterView.setVisibility(View.GONE);
+ }
}
@Override
@@ -147,6 +149,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
}
setMeasuredDimension(width, height);
+ invalidateOutline();
}
/** Synchronizes this view's properties with the task's transform */
@@ -201,9 +204,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
if (mConfig.launchedFromAppWithScreenshot) {
if (isTaskViewLaunchTargetTask) {
// Also hide the front most task bar view so we can animate it in
- mBarView.prepareEnterRecentsAnimation();
+ // mBarView.prepareEnterRecentsAnimation();
} else {
- // Don't do anything for the side views
+ // Don't do anything for the side views when animating in
}
} else if (mConfig.launchedFromAppWithThumbnail) {
@@ -232,17 +235,32 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
if (mConfig.launchedFromAppWithScreenshot) {
if (mTask.isLaunchTarget) {
- // XXX: We would have to animate the trasnlationY of the task view bar along with the clip and
- // reset it at the bottom
-
- // XXX: This should actually be the inset on the current app...
- mViewBounds.animateClipTop(taskRect.top, mConfig.taskViewEnterFromHomeDuration * 5);
- mViewBounds.animateClipBottom(getMeasuredHeight() - taskRect.bottom, mConfig.taskViewEnterFromHomeDuration * 5);
-
- animate().scaleX(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
- .scaleY(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
- .translationY(taskRect.top + transform.translationY)
- .setDuration(mConfig.taskViewEnterFromHomeDuration * 5)
+ int duration = mConfig.taskViewEnterFromHomeDuration * 5;
+ int windowInsetTop = mConfig.systemInsets.top; // XXX: Should be for the window
+ float taskScale = ((float) taskRect.width() / getMeasuredWidth()) * transform.scale;
+ float taskTranslationY = taskRect.top + transform.translationY - windowInsetTop;
+
+ // Animate the top clip
+ mViewBounds.animateClipTop(windowInsetTop, duration,
+ new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ int y = (Integer) animation.getAnimatedValue();
+ mBarView.setTranslationY(y);
+ }
+ });
+ // Animate the bottom or right clip
+ int size = Math.round((taskRect.width() / taskScale));
+ if (mConfig.hasHorizontalLayout()) {
+ mViewBounds.animateClipRight(getMeasuredWidth() - size, duration);
+ } else {
+ mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration);
+ }
+ animate()
+ .scaleX(taskScale)
+ .scaleY(taskScale)
+ .translationY(taskTranslationY)
+ .setDuration(duration)
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -424,11 +442,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
return mIsFullScreenView;
}
- /** Sets the stubbed state of this task view. */
- void setStubState(boolean isStub) {
- mIsStub = isStub;
- }
-
/**
* Returns whether this view should be clipped, or any views below should clip against this
* view.
@@ -447,7 +460,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Gets the max footer height. */
public int getMaxFooterHeight() {
- return mFooterView.mMaxFooterHeight;
+ if (mConfig.lockToAppEnabled) {
+ return mFooterView.mMaxFooterHeight;
+ } else {
+ return 0;
+ }
}
/** Animates the footer into and out of view. */
@@ -488,17 +505,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
setDim(getDimOverlayFromScale());
}
- /**** View drawing ****/
-
- @Override
- protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
- if (mIsStub && (child != mBarView)) {
- // Skip the thumbnail view if we are in stub mode
- return false;
- }
- return super.drawChild(canvas, child, drawingTime);
- }
-
/**** View focus state ****/
/**
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
index 6d5bb9de1a1a..108c8df0d944 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessController.java
@@ -163,15 +163,17 @@ public class BrightnessController implements ToggleSlider.Listener {
if (mListening) {
return;
}
+
mBrightnessObserver.startObserving();
mUserTracker.startTracking();
- // Update the slider and mode before attaching the listener so we don't receive the
- // onChanged notifications for the initial values.
+ // Update the slider and mode before attaching the listener so we don't
+ // receive the onChanged notifications for the initial values.
updateMode();
updateSlider();
mControl.setOnChangedListener(this);
+ mListening = true;
}
/** Unregister all call backs, both to and from the controller */
@@ -179,10 +181,11 @@ public class BrightnessController implements ToggleSlider.Listener {
if (!mListening) {
return;
}
+
mBrightnessObserver.stopObserving();
- mChangeCallbacks.clear();
mUserTracker.stopTracking();
mControl.setOnChangedListener(null);
+ mListening = false;
}
public void onChanged(ToggleSlider view, boolean tracking, boolean automatic, int value) {
diff --git a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
index 65e1cc6ef3e2..ad98168e1593 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/BrightnessDialog.java
@@ -16,6 +16,7 @@
package com.android.systemui.settings;
+import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.res.Resources;
@@ -30,76 +31,66 @@ import android.widget.ImageView;
import com.android.systemui.R;
/** A dialog that provides controls for adjusting the screen brightness. */
-public class BrightnessDialog extends Dialog implements
+public class BrightnessDialog extends Activity implements
BrightnessController.BrightnessStateChangeCallback {
-
- private static final String TAG = "BrightnessDialog";
- private static final boolean DEBUG = false;
-
- protected Handler mHandler = new Handler();
+ private final Handler mHandler = new Handler();
private BrightnessController mBrightnessController;
- private final int mBrightnessDialogLongTimeout;
- private final int mBrightnessDialogShortTimeout;
+ private int mBrightnessDialogLongTimeout;
+ private int mBrightnessDialogShortTimeout;
private final Runnable mDismissDialogRunnable = new Runnable() {
public void run() {
- if (BrightnessDialog.this.isShowing()) {
- BrightnessDialog.this.dismiss();
- }
+ finish();
};
};
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
- public BrightnessDialog(Context ctx) {
- super(ctx);
- Resources r = ctx.getResources();
- mBrightnessDialogLongTimeout =
- r.getInteger(R.integer.quick_settings_brightness_dialog_long_timeout);
- mBrightnessDialogShortTimeout =
- r.getInteger(R.integer.quick_settings_brightness_dialog_short_timeout);
- }
+ final Resources r = getResources();
+ mBrightnessDialogLongTimeout = r.getInteger(
+ R.integer.quick_settings_brightness_dialog_long_timeout);
+ mBrightnessDialogShortTimeout = r.getInteger(
+ R.integer.quick_settings_brightness_dialog_short_timeout);
+ final Window window = getWindow();
+ final WindowManager.LayoutParams lp = window.getAttributes();
- /**
- * Create the brightness dialog and any resources that are used for the
- * entire lifetime of the dialog.
- */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- Window window = getWindow();
- window.setGravity(Gravity.TOP);
- WindowManager.LayoutParams lp = window.getAttributes();
// Offset from the top
- lp.y = getContext().getResources().getDimensionPixelOffset(R.dimen.volume_panel_top);
+ lp.y = getResources().getDimensionPixelOffset(R.dimen.volume_panel_top);
lp.type = WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
- lp.privateFlags |=
- WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+ lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
+
window.setAttributes(lp);
+ window.setGravity(Gravity.TOP);
window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
window.requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.quick_settings_brightness_dialog);
- setCanceledOnTouchOutside(true);
}
-
@Override
protected void onStart() {
super.onStart();
- mBrightnessController = new BrightnessController(getContext(),
- (ImageView) findViewById(R.id.brightness_icon),
- (ToggleSlider) findViewById(R.id.brightness_slider));
+
+ final ImageView icon = (ImageView) findViewById(R.id.brightness_icon);
+ final ToggleSlider slider = (ToggleSlider) findViewById(R.id.brightness_slider);
+ mBrightnessController = new BrightnessController(this, icon, slider);
mBrightnessController.registerCallbacks();
- dismissBrightnessDialog(mBrightnessDialogLongTimeout);
mBrightnessController.addStateChangedCallback(this);
+
+ dismissBrightnessDialog(mBrightnessDialogLongTimeout);
}
@Override
protected void onStop() {
super.onStop();
+
+ mBrightnessController.removeStateChangedCallback(this);
mBrightnessController.unregisterCallbacks();
+
removeAllBrightnessDialogCallbacks();
}
@@ -109,6 +100,7 @@ public class BrightnessDialog extends Dialog implements
private void dismissBrightnessDialog(int timeout) {
removeAllBrightnessDialogCallbacks();
+
mHandler.postDelayed(mDismissDialogRunnable, timeout);
}
@@ -118,11 +110,12 @@ public class BrightnessDialog extends Dialog implements
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
- keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
- keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
- dismiss();
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
+ || keyCode == KeyEvent.KEYCODE_VOLUME_UP
+ || keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
+ finish();
}
+
return super.onKeyDown(keyCode, event);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java b/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
deleted file mode 100644
index 8bc72c93fa01..000000000000
--- a/packages/SystemUI/src/com/android/systemui/settings/SettingsUI.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * 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.settings;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Handler;
-import android.os.UserHandle;
-import android.util.Log;
-
-import com.android.systemui.SystemUI;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
-
-public class SettingsUI extends SystemUI {
- private static final String TAG = "SettingsUI";
- private static final boolean DEBUG = false;
-
- private final Handler mHandler = new Handler();
- private BrightnessDialog mBrightnessDialog;
-
- private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (action.equals(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG)) {
- if (DEBUG) Log.d(TAG, "showing brightness dialog");
-
- if (mBrightnessDialog == null) {
- mBrightnessDialog = new BrightnessDialog(mContext);
- mBrightnessDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
- @Override
- public void onDismiss(DialogInterface dialog) {
- mBrightnessDialog = null;
- }
- });
- }
-
- if (!mBrightnessDialog.isShowing()) {
- mBrightnessDialog.show();
- }
-
- } else {
- Log.w(TAG, "unknown intent: " + intent);
- }
- }
- };
-
- public void start() {
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
- mContext.registerReceiverAsUser(mIntentReceiver, UserHandle.ALL, filter, null, mHandler);
- }
-
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- pw.print("mBrightnessDialog=");
- pw.println(mBrightnessDialog == null ? "null" : mBrightnessDialog.toString());
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index c464f3168678..cf930bddead3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -44,12 +44,13 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
private static final int TAG_KEY_ANIM = R.id.scrim;
private static final int NUM_TEASES = 3;
- private static final long TEASE_IN_ANIMATION_DURATION = 500;
- private static final long TEASE_VISIBLE_DURATION = 3000;
+ private static final long TEASE_IN_ANIMATION_DURATION = 1000;
+ private static final long TEASE_VISIBLE_DURATION = 2000;
private static final long TEASE_OUT_ANIMATION_DURATION = 1000;
private static final long TEASE_INVISIBLE_DURATION = 1000;
private static final long TEASE_DURATION = TEASE_IN_ANIMATION_DURATION
+ TEASE_VISIBLE_DURATION + TEASE_OUT_ANIMATION_DURATION + TEASE_INVISIBLE_DURATION;
+ private static final long PRE_TEASE_DELAY = 1000;
private final View mScrimBehind;
private final View mScrimInFront;
@@ -128,8 +129,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener {
public long tease() {
if (!mDozing) return 0;
mTeasesRemaining = NUM_TEASES;
- mScrimInFront.post(mTeaseIn);
- return NUM_TEASES * TEASE_DURATION;
+ mScrimInFront.postDelayed(mTeaseIn, PRE_TEASE_DELAY);
+ return PRE_TEASE_DELAY + NUM_TEASES * TEASE_DURATION;
}
private void cancelTeasing() {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 71f1d2118814..44a53448ccb7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -2339,8 +2339,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.System.putIntForUser(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS, brightness,
UserHandle.USER_CURRENT_OR_SELF);
- Intent intent = new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG);
- mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF);
+ mContext.startActivityAsUser(new Intent(Intent.ACTION_SHOW_BRIGHTNESS_DIALOG),
+ UserHandle.CURRENT_OR_SELF);
}
return -1;
} else if (keyCode == KeyEvent.KEYCODE_META_LEFT) {
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index bae2d223045b..3a4e2ee63a05 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -28,6 +28,7 @@ import com.android.server.location.GeofenceManager;
import com.android.server.location.GeofenceProxy;
import com.android.server.location.GpsLocationProvider;
import com.android.server.location.GpsMeasurementsProvider;
+import com.android.server.location.GpsNavigationMessageProvider;
import com.android.server.location.LocationBlacklist;
import com.android.server.location.LocationFudger;
import com.android.server.location.LocationProviderInterface;
@@ -60,6 +61,7 @@ import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
import android.location.IGpsMeasurementsListener;
+import android.location.IGpsNavigationMessageListener;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
import android.location.ILocationListener;
@@ -159,6 +161,7 @@ public class LocationManagerService extends ILocationManager.Stub {
private PassiveProvider mPassiveProvider; // track passive provider for special cases
private LocationBlacklist mBlacklist;
private GpsMeasurementsProvider mGpsMeasurementsProvider;
+ private GpsNavigationMessageProvider mGpsNavigationMessageProvider;
// --- fields below are protected by mLock ---
// Set of providers that are explicitly enabled
@@ -409,6 +412,7 @@ public class LocationManagerService extends ILocationManager.Stub {
mRealProviders.put(LocationManager.GPS_PROVIDER, gpsProvider);
}
mGpsMeasurementsProvider = gpsProvider.getGpsMeasurementsProvider();
+ mGpsNavigationMessageProvider = gpsProvider.getGpsNavigationMessageProvider();
/*
Load package name(s) containing location provider support.
@@ -1847,7 +1851,6 @@ public class LocationManagerService extends ILocationManager.Stub {
if (!hasLocationAccess) {
return false;
}
-
return mGpsMeasurementsProvider.addListener(listener);
}
@@ -1857,6 +1860,35 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
+ public boolean addGpsNavigationMessageListener(
+ IGpsNavigationMessageListener listener,
+ String packageName) {
+ int allowedResolutionLevel = getCallerAllowedResolutionLevel();
+ checkResolutionLevelIsSufficientForProviderUse(
+ allowedResolutionLevel,
+ LocationManager.GPS_PROVIDER);
+
+ int uid = Binder.getCallingUid();
+ long identity = Binder.clearCallingIdentity();
+ boolean hasLocationAccess;
+ try {
+ hasLocationAccess = checkLocationAccess(uid, packageName, allowedResolutionLevel);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ if (!hasLocationAccess) {
+ return false;
+ }
+ return mGpsNavigationMessageProvider.addListener(listener);
+ }
+
+ @Override
+ public boolean removeGpsNavigationMessageListener(IGpsNavigationMessageListener listener) {
+ return mGpsNavigationMessageProvider.removeListener(listener);
+ }
+
+ @Override
public boolean sendExtraCommand(String provider, String command, Bundle extras) {
if (provider == null) {
// throw NullPointerException to remain compatible with previous implementation
diff --git a/services/core/java/com/android/server/job/JobMapReadFinishedListener.java b/services/core/java/com/android/server/job/JobMapReadFinishedListener.java
deleted file mode 100644
index f3e77e6a36f6..000000000000
--- a/services/core/java/com/android/server/job/JobMapReadFinishedListener.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2014 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.server.job;
-
-import java.util.List;
-
-import com.android.server.job.controllers.JobStatus;
-
-/**
- * Callback definition for I/O thread to let the JobManagerService know when
- * I/O read has completed. Done this way so we don't stall the main thread on
- * boot.
- */
-public interface JobMapReadFinishedListener {
-
- /**
- * Called by the {@link JobStore} at boot, when the disk read is finished.
- */
- public void onJobMapReadFinished(List<JobStatus> jobs);
-}
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 3b52bafc3ff7..587f596e420d 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -69,7 +69,7 @@ import com.android.server.job.controllers.TimeController;
* @hide
*/
public class JobSchedulerService extends com.android.server.SystemService
- implements StateChangedListener, JobCompletedListener, JobMapReadFinishedListener {
+ implements StateChangedListener, JobCompletedListener {
// TODO: Switch this off for final version.
static final boolean DEBUG = true;
/** The number of concurrent jobs we run at one time. */
@@ -487,28 +487,6 @@ public class JobSchedulerService extends com.android.server.SystemService
mHandler.obtainMessage(MSG_JOB_EXPIRED, jobStatus).sendToTarget();
}
- /**
- * Disk I/O is finished, take the list of jobs we read from disk and add them to our
- * {@link JobStore}.
- * This is run on the {@link com.android.server.IoThread} instance, which is a separate thread,
- * and is called once at boot.
- */
- @Override
- public void onJobMapReadFinished(List<JobStatus> jobs) {
- synchronized (mJobs) {
- for (int i=0; i<jobs.size(); i++) {
- JobStatus js = jobs.get(i);
- if (mJobs.containsJobIdForUid(js.getJobId(), js.getUid())) {
- // An app with BOOT_COMPLETED *might* have decided to reschedule their job, in
- // the same amount of time it took us to read it from disk. If this is the case
- // we leave it be.
- continue;
- }
- startTrackingJob(js);
- }
- }
- }
-
private class JobHandler extends Handler {
public JobHandler(Looper looper) {
diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java
index 48312b04c9bd..46f557f5e1bb 100644
--- a/services/core/java/com/android/server/job/JobStore.java
+++ b/services/core/java/com/android/server/job/JobStore.java
@@ -88,19 +88,26 @@ public class JobStore {
synchronized (sSingletonLock) {
if (sSingleton == null) {
sSingleton = new JobStore(jobManagerService.getContext(),
- Environment.getDataDirectory(), jobManagerService);
+ Environment.getDataDirectory());
}
return sSingleton;
}
}
+ /**
+ * @return A freshly initialized job store object, with no loaded jobs.
+ */
@VisibleForTesting
- public static JobStore initAndGetForTesting(Context context, File dataDir,
- JobMapReadFinishedListener callback) {
- return new JobStore(context, dataDir, callback);
+ public static JobStore initAndGetForTesting(Context context, File dataDir) {
+ JobStore jobStoreUnderTest = new JobStore(context, dataDir);
+ jobStoreUnderTest.clear();
+ return jobStoreUnderTest;
}
- private JobStore(Context context, File dataDir, JobMapReadFinishedListener callback) {
+ /**
+ * Construct the instance of the job store. This results in a blocking read from disk.
+ */
+ private JobStore(Context context, File dataDir) {
mContext = context;
mDirtyOperations = 0;
@@ -111,7 +118,7 @@ public class JobStore {
mJobSet = new ArraySet<JobStatus>();
- readJobMapFromDiskAsync(callback);
+ readJobMapFromDisk(mJobSet);
}
/**
@@ -249,12 +256,9 @@ public class JobStore {
}
}
- private void readJobMapFromDiskAsync(JobMapReadFinishedListener callback) {
- mIoHandler.post(new ReadJobMapFromDiskRunnable(callback));
- }
-
- public void readJobMapFromDisk(JobMapReadFinishedListener callback) {
- new ReadJobMapFromDiskRunnable(callback).run();
+ @VisibleForTesting
+ public void readJobMapFromDisk(ArraySet<JobStatus> jobSet) {
+ new ReadJobMapFromDiskRunnable(jobSet).run();
}
/**
@@ -398,13 +402,18 @@ public class JobStore {
}
/**
- * Runnable that reads list of persisted job from xml.
- * NOTE: This Runnable locks on JobStore.this
+ * Runnable that reads list of persisted job from xml. This is run once at start up, so doesn't
+ * need to go through {@link JobStore#add(com.android.server.job.controllers.JobStatus)}.
*/
private class ReadJobMapFromDiskRunnable implements Runnable {
- private JobMapReadFinishedListener mCallback;
- public ReadJobMapFromDiskRunnable(JobMapReadFinishedListener callback) {
- mCallback = callback;
+ private final ArraySet<JobStatus> jobSet;
+
+ /**
+ * @param jobSet Reference to the (empty) set of JobStatus objects that back the JobStore,
+ * so that after disk read we can populate it directly.
+ */
+ ReadJobMapFromDiskRunnable(ArraySet<JobStatus> jobSet) {
+ this.jobSet = jobSet;
}
@Override
@@ -414,11 +423,13 @@ public class JobStore {
FileInputStream fis = mJobsFile.openRead();
synchronized (JobStore.this) {
jobs = readJobMapImpl(fis);
+ if (jobs != null) {
+ for (int i=0; i<jobs.size(); i++) {
+ this.jobSet.add(jobs.get(i));
+ }
+ }
}
fis.close();
- if (jobs != null) {
- mCallback.onJobMapReadFinished(jobs);
- }
} catch (FileNotFoundException e) {
if (JobSchedulerService.DEBUG) {
Slog.d(TAG, "Could not find jobs file, probably there was nothing to load.");
@@ -673,4 +684,4 @@ public class JobStore {
return Pair.create(earliestRunTimeElapsed, latestRunTimeElapsed);
}
}
-} \ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java
index 09873c7383b9..058a23e36b14 100644
--- a/services/core/java/com/android/server/location/GpsLocationProvider.java
+++ b/services/core/java/com/android/server/location/GpsLocationProvider.java
@@ -38,6 +38,7 @@ import android.hardware.location.GeofenceHardwareImpl;
import android.location.Criteria;
import android.location.FusedBatchOptions;
import android.location.GpsMeasurementsEvent;
+import android.location.GpsNavigationMessageEvent;
import android.location.IGpsGeofenceHardware;
import android.location.IGpsStatusListener;
import android.location.IGpsStatusProvider;
@@ -324,6 +325,14 @@ public class GpsLocationProvider implements LocationProviderInterface {
protected boolean isSupported() {
return GpsLocationProvider.isSupported();
}
+
+ @Override
+ protected boolean registerWithService() {
+ return true;
+ }
+
+ @Override
+ protected void unregisterFromService() {}
};
// Handler for processing events
@@ -374,16 +383,34 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
@Override
- protected void onFirstListenerAdded() {
- native_start_measurement_collection();
+ protected boolean registerWithService() {
+ return native_start_measurement_collection();
}
@Override
- protected void onLastListenerRemoved() {
+ protected void unregisterFromService() {
native_stop_measurement_collection();
}
};
+ private final GpsNavigationMessageProvider mGpsNavigationMessageProvider =
+ new GpsNavigationMessageProvider() {
+ @Override
+ protected boolean isSupported() {
+ return native_is_navigation_message_supported();
+ }
+
+ @Override
+ protected boolean registerWithService() {
+ return native_start_navigation_message_collection();
+ }
+
+ @Override
+ protected void unregisterFromService() {
+ native_stop_navigation_message_collection();
+ }
+ };
+
public IGpsStatusProvider getGpsStatusProvider() {
return mGpsStatusProvider;
}
@@ -396,6 +423,10 @@ public class GpsLocationProvider implements LocationProviderInterface {
return mGpsMeasurementsProvider;
}
+ public GpsNavigationMessageProvider getGpsNavigationMessageProvider() {
+ return mGpsNavigationMessageProvider;
+ }
+
private final BroadcastReceiver mBroadcastReciever = new BroadcastReceiver() {
@Override public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
@@ -1357,13 +1388,20 @@ public class GpsLocationProvider implements LocationProviderInterface {
}
/**
- * called from native code - Gps Data callback
+ * called from native code - Gps measurements callback
*/
private void reportMeasurementData(GpsMeasurementsEvent event) {
mGpsMeasurementsProvider.onMeasurementsAvailable(event);
}
/**
+ * called from native code - GPS navigation message callback
+ */
+ private void reportNavigationMessage(GpsNavigationMessageEvent event) {
+ mGpsNavigationMessageProvider.onNavigationMessageAvailable(event);
+ }
+
+ /**
* called from native code to inform us what the GPS engine capabilities are
*/
private void setEngineCapabilities(int capabilities) {
@@ -1954,6 +1992,11 @@ public class GpsLocationProvider implements LocationProviderInterface {
// Gps Hal measurements support.
private static native boolean native_is_measurement_supported();
- private static native boolean native_start_measurement_collection();
- private static native boolean native_stop_measurement_collection();
+ private native boolean native_start_measurement_collection();
+ private native boolean native_stop_measurement_collection();
+
+ // Gps Navigation message support.
+ private static native boolean native_is_navigation_message_supported();
+ private native boolean native_start_navigation_message_collection();
+ private native boolean native_stop_navigation_message_collection();
}
diff --git a/services/core/java/com/android/server/location/GpsMeasurementsProvider.java b/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
index 001f638ede50..1c48257b770d 100644
--- a/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GpsMeasurementsProvider.java
@@ -29,6 +29,9 @@ import android.os.RemoteException;
*/
public abstract class GpsMeasurementsProvider
extends RemoteListenerHelper<IGpsMeasurementsListener> {
+ public GpsMeasurementsProvider() {
+ super("GpsMeasurementsProvider");
+ }
public void onMeasurementsAvailable(final GpsMeasurementsEvent event) {
ListenerOperation<IGpsMeasurementsListener> operation =
diff --git a/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java b/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java
new file mode 100644
index 000000000000..fca7378d3946
--- /dev/null
+++ b/services/core/java/com/android/server/location/GpsNavigationMessageProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014 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.server.location;
+
+import android.location.GpsNavigationMessageEvent;
+import android.location.IGpsNavigationMessageListener;
+import android.os.RemoteException;
+
+/**
+ * An base implementation for GPS navigation messages provider.
+ * It abstracts out the responsibility of handling listeners, while still allowing technology
+ * specific implementations to be built.
+ *
+ * @hide
+ */
+public abstract class GpsNavigationMessageProvider
+ extends RemoteListenerHelper<IGpsNavigationMessageListener> {
+ public GpsNavigationMessageProvider() {
+ super("GpsNavigationMessageProvider");
+ }
+
+ public void onNavigationMessageAvailable(final GpsNavigationMessageEvent event) {
+ ListenerOperation<IGpsNavigationMessageListener> operation =
+ new ListenerOperation<IGpsNavigationMessageListener>() {
+ @Override
+ public void execute(IGpsNavigationMessageListener listener)
+ throws RemoteException {
+ listener.onGpsNavigationMessageReceived(event);
+ }
+ };
+
+ foreach(operation);
+ }
+}
diff --git a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java b/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
index b741e75c4452..27cf3d893bd8 100644
--- a/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
+++ b/services/core/java/com/android/server/location/GpsStatusListenerHelper.java
@@ -23,6 +23,10 @@ import android.os.RemoteException;
* Implementation of a handler for {@link IGpsStatusListener}.
*/
abstract class GpsStatusListenerHelper extends RemoteListenerHelper<IGpsStatusListener> {
+ public GpsStatusListenerHelper() {
+ super("GpsStatusListenerHelper");
+ }
+
public void onFirstFix(final int timeToFirstFix) {
Operation operation = new Operation() {
@Override
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index 79335f73060c..451af18d1243 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -32,16 +32,19 @@ import java.util.HashMap;
* A helper class, that handles operations in remote listeners, and tracks for remote process death.
*/
abstract class RemoteListenerHelper<TListener extends IInterface> {
- private static final String TAG = "RemoteListenerHelper";
-
+ private final String mTag;
private final HashMap<IBinder, LinkedListener> mListenerMap =
new HashMap<IBinder, LinkedListener>();
+ protected RemoteListenerHelper(String name) {
+ Preconditions.checkNotNull(name);
+ mTag = name;
+ }
+
public boolean addListener(@NonNull TListener listener) {
Preconditions.checkNotNull(listener, "Attempted to register a 'null' listener.");
-
if (!isSupported()) {
- Log.e(TAG, "Refused to add listener, the feature is not supported.");
+ Log.e(mTag, "Refused to add listener, the feature is not supported.");
return false;
}
@@ -58,13 +61,17 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
} catch (RemoteException e) {
// if the remote process registering the listener is already death, just swallow the
// exception and continue
- Log.e(TAG, "Remote listener already died.", e);
+ Log.e(mTag, "Remote listener already died.", e);
return false;
}
mListenerMap.put(binder, deathListener);
if (mListenerMap.size() == 1) {
- onFirstListenerAdded();
+ if (!registerWithService()) {
+ Log.e(mTag, "RegisterWithService failed, listener will be removed.");
+ removeListener(listener);
+ return false;
+ }
}
}
@@ -73,9 +80,8 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
public boolean removeListener(@NonNull TListener listener) {
Preconditions.checkNotNull(listener, "Attempted to remove a 'null' listener.");
-
if (!isSupported()) {
- Log.e(TAG, "Refused to remove listener, the feature is not supported.");
+ Log.e(mTag, "Refused to remove listener, the feature is not supported.");
return false;
}
@@ -84,26 +90,19 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
synchronized (mListenerMap) {
linkedListener = mListenerMap.remove(binder);
if (mListenerMap.isEmpty() && linkedListener != null) {
- onLastListenerRemoved();
+ unregisterFromService();
}
}
if (linkedListener != null) {
binder.unlinkToDeath(linkedListener, 0 /* flags */);
}
-
return true;
}
protected abstract boolean isSupported();
-
- protected void onFirstListenerAdded() {
- // event triggered when the first listener has been added
- }
-
- protected void onLastListenerRemoved() {
- // event triggered when the last listener has bee removed
- }
+ protected abstract boolean registerWithService();
+ protected abstract void unregisterFromService();
protected interface ListenerOperation<TListener extends IInterface> {
void execute(TListener listener) throws RemoteException;
@@ -121,7 +120,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
try {
operation.execute(listener);
} catch (RemoteException e) {
- Log.e(TAG, "Error in monitored listener.", e);
+ Log.e(mTag, "Error in monitored listener.", e);
removeListener(listener);
}
}
@@ -141,7 +140,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
@Override
public void binderDied() {
- Log.d(TAG, "Remote Listener died: " + mListener);
+ Log.d(mTag, "Remote Listener died: " + mListener);
removeListener(mListener);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 69f2f32ac7c0..b96f67299085 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -138,7 +138,6 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Environment.UserEnvironment;
-import android.os.FileObserver;
import android.os.FileUtils;
import android.os.Handler;
import android.os.IBinder;
@@ -235,7 +234,6 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_PACKAGE_INFO = false;
private static final boolean DEBUG_INTENT_MATCHING = false;
private static final boolean DEBUG_PACKAGE_SCANNING = false;
- private static final boolean DEBUG_APP_DIR_OBSERVER = false;
private static final boolean DEBUG_VERIFY = false;
private static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
@@ -249,12 +247,6 @@ public class PackageManagerService extends IPackageManager.Stub {
// Cap the size of permission trees that 3rd party apps can define
private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768; // characters of text
- private static final int REMOVE_EVENTS =
- FileObserver.CLOSE_WRITE | FileObserver.DELETE | FileObserver.MOVED_FROM;
- private static final int ADD_EVENTS =
- FileObserver.CLOSE_WRITE /*| FileObserver.CREATE*/ | FileObserver.MOVED_TO;
-
- private static final int OBSERVER_EVENTS = REMOVE_EVENTS | ADD_EVENTS;
// Suffix used during package installation when copying/moving
// package apks to install directory.
private static final String INSTALL_PACKAGE_SUFFIX = "-";
@@ -342,30 +334,6 @@ public class PackageManagerService extends IPackageManager.Stub {
/** The location for ASEC container files on internal storage. */
final String mAsecInternalPath;
- // This is the object monitoring the framework dir.
- final FileObserver mFrameworkInstallObserver;
-
- // This is the object monitoring the system app dir.
- final FileObserver mSystemInstallObserver;
-
- // This is the object monitoring the privileged system app dir.
- final FileObserver mPrivilegedInstallObserver;
-
- // This is the object monitoring the vendor app dir.
- final FileObserver mVendorInstallObserver;
-
- // This is the object monitoring the vendor overlay package dir.
- final FileObserver mVendorOverlayInstallObserver;
-
- // This is the object monitoring the OEM app dir.
- final FileObserver mOemInstallObserver;
-
- // This is the object monitoring mAppInstallDir.
- final FileObserver mAppInstallObserver;
-
- // This is the object monitoring mDrmAppPrivateInstallDir.
- final FileObserver mDrmAppInstallObserver;
-
// Used for privilege escalation. MUST NOT BE CALLED WITH mPackages
// LOCK HELD. Can be called with mInstallLock held.
final Installer mInstaller;
@@ -1542,16 +1510,10 @@ public class PackageManagerService extends IPackageManager.Stub {
// For security and version matching reason, only consider
// overlay packages if they reside in VENDOR_OVERLAY_DIR.
File vendorOverlayDir = new File(VENDOR_OVERLAY_DIR);
- mVendorOverlayInstallObserver = new AppDirObserver(
- vendorOverlayDir.getPath(), OBSERVER_EVENTS, true, false);
- mVendorOverlayInstallObserver.startWatching();
scanDirLI(vendorOverlayDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode | SCAN_TRUSTED_OVERLAY, 0);
// Find base frameworks (resource packages without code).
- mFrameworkInstallObserver = new AppDirObserver(
- frameworkDir.getPath(), OBSERVER_EVENTS, true, false);
- mFrameworkInstallObserver.startWatching();
scanDirLI(frameworkDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED,
@@ -1559,18 +1521,12 @@ public class PackageManagerService extends IPackageManager.Stub {
// Collected privileged system packages.
File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
- mPrivilegedInstallObserver = new AppDirObserver(
- privilegedAppDir.getPath(), OBSERVER_EVENTS, true, true);
- mPrivilegedInstallObserver.startWatching();
scanDirLI(privilegedAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
// Collect ordinary system packages.
File systemAppDir = new File(Environment.getRootDirectory(), "app");
- mSystemInstallObserver = new AppDirObserver(
- systemAppDir.getPath(), OBSERVER_EVENTS, true, false);
- mSystemInstallObserver.startWatching();
scanDirLI(systemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
@@ -1581,17 +1537,11 @@ public class PackageManagerService extends IPackageManager.Stub {
} catch (IOException e) {
// failed to look up canonical path, continue with original one
}
- mVendorInstallObserver = new AppDirObserver(
- vendorAppDir.getPath(), OBSERVER_EVENTS, true, false);
- mVendorInstallObserver.startWatching();
scanDirLI(vendorAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
// Collect all OEM packages.
File oemAppDir = new File(Environment.getOemDirectory(), "app");
- mOemInstallObserver = new AppDirObserver(
- oemAppDir.getPath(), OBSERVER_EVENTS, true, false);
- mOemInstallObserver.startWatching();
scanDirLI(oemAppDir, PackageParser.PARSE_IS_SYSTEM
| PackageParser.PARSE_IS_SYSTEM_DIR, scanMode, 0);
@@ -1665,14 +1615,8 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
- mAppInstallObserver = new AppDirObserver(
- mAppInstallDir.getPath(), OBSERVER_EVENTS, false, false);
- mAppInstallObserver.startWatching();
scanDirLI(mAppInstallDir, 0, scanMode, 0);
-
- mDrmAppInstallObserver = new AppDirObserver(
- mDrmAppPrivateInstallDir.getPath(), OBSERVER_EVENTS, false, false);
- mDrmAppInstallObserver.startWatching();
+
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
scanMode, 0);
@@ -1703,9 +1647,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
reportSettingsProblem(Log.WARN, msg);
}
- } else {
- mAppInstallObserver = null;
- mDrmAppInstallObserver = null;
}
// Now that we know all of the shared libraries, update all clients to have
@@ -7723,131 +7664,6 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
-
- private final class AppDirObserver extends FileObserver {
- public AppDirObserver(String path, int mask, boolean isrom, boolean isPrivileged) {
- super(path, mask);
- mRootDir = path;
- mIsRom = isrom;
- mIsPrivileged = isPrivileged;
- }
-
- public void onEvent(int event, String path) {
- String removedPackage = null;
- int removedAppId = -1;
- int[] removedUsers = null;
- String addedPackage = null;
- int addedAppId = -1;
- int[] addedUsers = null;
-
- // TODO post a message to the handler to obtain serial ordering
- synchronized (mInstallLock) {
- String fullPathStr = null;
- File fullPath = null;
- if (path != null) {
- fullPath = new File(mRootDir, path);
- fullPathStr = fullPath.getPath();
- }
-
- if (DEBUG_APP_DIR_OBSERVER)
- Log.v(TAG, "File " + fullPathStr + " changed: " + Integer.toHexString(event));
-
- if (!isApkFile(fullPath)) {
- if (DEBUG_APP_DIR_OBSERVER)
- Log.v(TAG, "Ignoring change of non-package file: " + fullPathStr);
- return;
- }
-
- // Ignore packages that are being installed or
- // have just been installed.
- if (ignoreCodePath(fullPathStr)) {
- return;
- }
- PackageParser.Package p = null;
- PackageSetting ps = null;
- // reader
- synchronized (mPackages) {
- p = mAppDirs.get(fullPathStr);
- if (p != null) {
- ps = mSettings.mPackages.get(p.applicationInfo.packageName);
- if (ps != null) {
- removedUsers = ps.queryInstalledUsers(sUserManager.getUserIds(), true);
- } else {
- removedUsers = sUserManager.getUserIds();
- }
- }
- addedUsers = sUserManager.getUserIds();
- }
- if ((event&REMOVE_EVENTS) != 0) {
- if (ps != null) {
- if (DEBUG_REMOVE) Slog.d(TAG, "Package disappeared: " + ps);
- removePackageLI(ps, true);
- removedPackage = ps.name;
- removedAppId = ps.appId;
- }
- }
-
- if ((event&ADD_EVENTS) != 0) {
- if (p == null) {
- if (DEBUG_INSTALL) Slog.d(TAG, "New file appeared: " + fullPath);
- int flags = PackageParser.PARSE_CHATTY | PackageParser.PARSE_MUST_BE_APK;
- if (mIsRom) {
- flags |= PackageParser.PARSE_IS_SYSTEM
- | PackageParser.PARSE_IS_SYSTEM_DIR;
- if (mIsPrivileged) {
- flags |= PackageParser.PARSE_IS_PRIVILEGED;
- }
- }
- try {
- p = scanPackageLI(fullPath, flags,
- SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
- System.currentTimeMillis(), UserHandle.ALL, null);
- } catch (PackageManagerException e) {
- Slog.w(TAG, "Failed to scan " + fullPath + ": " + e.getMessage());
- p = null;
- }
- if (p != null) {
- /*
- * TODO this seems dangerous as the package may have
- * changed since we last acquired the mPackages
- * lock.
- */
- // writer
- synchronized (mPackages) {
- updatePermissionsLPw(p.packageName, p,
- p.permissions.size() > 0 ? UPDATE_PERMISSIONS_ALL : 0);
- }
- addedPackage = p.applicationInfo.packageName;
- addedAppId = UserHandle.getAppId(p.applicationInfo.uid);
- }
- }
- }
-
- // reader
- synchronized (mPackages) {
- mSettings.writeLPr();
- }
- }
-
- if (removedPackage != null) {
- Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, removedAppId);
- extras.putBoolean(Intent.EXTRA_DATA_REMOVED, false);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage,
- extras, null, null, removedUsers);
- }
- if (addedPackage != null) {
- Bundle extras = new Bundle(1);
- extras.putInt(Intent.EXTRA_UID, addedAppId);
- sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, addedPackage,
- extras, null, null, addedUsers);
- }
- }
-
- private final String mRootDir;
- private final boolean mIsRom;
- private final boolean mIsPrivileged;
- }
@Override
public void installPackage(String originPath, IPackageInstallObserver2 observer, int flags,
diff --git a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
index 8bb6e8a6cc9e..46327d7db897 100644
--- a/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GpsLocationProvider.cpp
@@ -53,6 +53,7 @@ static jmethodID method_reportGeofenceRemoveStatus;
static jmethodID method_reportGeofencePauseStatus;
static jmethodID method_reportGeofenceResumeStatus;
static jmethodID method_reportMeasurementData;
+static jmethodID method_reportNavigationMessages;
static const GpsInterface* sGpsInterface = NULL;
static const GpsXtraInterface* sGpsXtraInterface = NULL;
@@ -62,6 +63,7 @@ static const GpsDebugInterface* sGpsDebugInterface = NULL;
static const AGpsRilInterface* sAGpsRilInterface = NULL;
static const GpsGeofencingInterface* sGpsGeofencingInterface = NULL;
static const GpsMeasurementInterface* sGpsMeasurementInterface = NULL;
+static const GpsNavigationMessageInterface* sGpsNavigationMessageInterface = NULL;
// temporary storage for GPS callbacks
static GpsSvStatus sGpsSvStatus;
@@ -447,6 +449,10 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
clazz,
"reportMeasurementData",
"(Landroid/location/GpsMeasurementsEvent;)V");
+ method_reportNavigationMessages = env->GetMethodID(
+ clazz,
+ "reportNavigationMessage",
+ "(Landroid/location/GpsNavigationMessageEvent;)V");
err = hw_get_module(GPS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0) {
@@ -472,6 +478,9 @@ static void android_location_GpsLocationProvider_class_init_native(JNIEnv* env,
(const GpsGeofencingInterface*)sGpsInterface->get_extension(GPS_GEOFENCING_INTERFACE);
sGpsMeasurementInterface =
(const GpsMeasurementInterface*)sGpsInterface->get_extension(GPS_MEASUREMENT_INTERFACE);
+ sGpsNavigationMessageInterface =
+ (const GpsNavigationMessageInterface*)sGpsInterface->get_extension(
+ GPS_NAVIGATION_MESSAGE_INTERFACE);
}
}
@@ -1212,7 +1221,6 @@ static void measurement_callback(GpsData* data) {
checkAndClearExceptionFromCallback(env, __FUNCTION__);
} else {
ALOGE("Invalid GpsData size found in gps_measurement_callback, size=%d", data->size);
- return;
}
}
@@ -1223,7 +1231,7 @@ GpsMeasurementCallbacks sGpsMeasurementCallbacks = {
static jboolean android_location_GpsLocationProvider_is_measurement_supported(
JNIEnv* env,
- jobject obj) {
+ jclass clazz) {
if (sGpsMeasurementInterface != NULL) {
return JNI_TRUE;
}
@@ -1259,6 +1267,110 @@ static jboolean android_location_GpsLocationProvider_stop_measurement_collection
return JNI_TRUE;
}
+static jobject translate_gps_navigation_message(JNIEnv* env, GpsNavigationMessage* message) {
+ size_t dataLength = message->data_length;
+ uint8_t* data = message->data;
+ if (dataLength == 0 || data == NULL) {
+ ALOGE("Invalid Navigation Message found: data=%p, length=%d", data, dataLength);
+ return NULL;
+ }
+
+ jclass navigationMessageClass = env->FindClass("android/location/GpsNavigationMessage");
+ jmethodID navigationMessageCtor = env->GetMethodID(navigationMessageClass, "<init>", "()V");
+ jobject navigationMessageObject = env->NewObject(navigationMessageClass, navigationMessageCtor);
+
+ jmethodID setTypeMethod = env->GetMethodID(navigationMessageClass, "setType", "(B)V");
+ env->CallVoidMethod(navigationMessageObject, setTypeMethod, message->type);
+
+ jmethodID setPrnMethod = env->GetMethodID(navigationMessageClass, "setPrn", "(B)V");
+ env->CallVoidMethod(navigationMessageObject, setPrnMethod, message->prn);
+
+ jmethodID setMessageIdMethod = env->GetMethodID(navigationMessageClass, "setMessageId", "(S)V");
+ env->CallVoidMethod(navigationMessageObject, setMessageIdMethod, message->message_id);
+
+ jmethodID setSubmessageIdMethod =
+ env->GetMethodID(navigationMessageClass, "setSubmessageId", "(S)V");
+ env->CallVoidMethod(navigationMessageObject, setSubmessageIdMethod, message->submessage_id);
+
+ jbyteArray dataArray = env->NewByteArray(dataLength);
+ env->SetByteArrayRegion(dataArray, 0, dataLength, (jbyte*) data);
+ jmethodID setDataMethod = env->GetMethodID(navigationMessageClass, "setData", "([B)V");
+ env->CallVoidMethod(navigationMessageObject, setDataMethod, dataArray);
+
+ return navigationMessageObject;
+}
+
+static void navigation_message_callback(GpsNavigationMessage* message) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (message == NULL) {
+ ALOGE("Invalid Navigation Message provided to callback");
+ return;
+ }
+
+ if (message->size == sizeof(GpsNavigationMessage)) {
+ jobject navigationMessage = translate_gps_navigation_message(env, message);
+
+ jclass navigationMessageEventClass =
+ env->FindClass("android/location/GpsNavigationMessageEvent");
+ jmethodID navigationMessageEventCtor = env->GetMethodID(
+ navigationMessageEventClass,
+ "<init>",
+ "(Landroid/location/GpsNavigationMessage;)V");
+ jobject navigationMessageEvent = env->NewObject(
+ navigationMessageEventClass,
+ navigationMessageEventCtor,
+ navigationMessage);
+
+ env->CallVoidMethod(mCallbacksObj, method_reportNavigationMessages, navigationMessageEvent);
+ checkAndClearExceptionFromCallback(env, __FUNCTION__);
+ } else {
+ ALOGE("Invalid GpsNavigationMessage size found: %d", message->size);
+ }
+}
+
+GpsNavigationMessageCallbacks sGpsNavigationMessageCallbacks = {
+ sizeof(GpsNavigationMessageCallbacks),
+ navigation_message_callback,
+};
+
+static jboolean android_location_GpsLocationProvider_is_navigation_message_supported(
+ JNIEnv* env,
+ jclass clazz) {
+ if(sGpsNavigationMessageInterface != NULL) {
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+static jboolean android_location_GpsLocationProvider_start_navigation_message_collection(
+ JNIEnv* env,
+ jobject obj) {
+ if (sGpsNavigationMessageInterface == NULL) {
+ ALOGE("Navigation Message interface is not available.");
+ return JNI_FALSE;
+ }
+
+ int result = sGpsNavigationMessageInterface->init(&sGpsNavigationMessageCallbacks);
+ if (result != GPS_NAVIGATION_MESSAGE_OPERATION_SUCCESS) {
+ ALOGE("An error has been found in %s: %d", __FUNCTION__, result);
+ return JNI_FALSE;
+ }
+
+ return JNI_TRUE;
+}
+
+static jboolean android_location_GpsLocationProvider_stop_navigation_message_collection(
+ JNIEnv* env,
+ jobject obj) {
+ if (sGpsNavigationMessageInterface == NULL) {
+ ALOGE("Navigation Message interface is not available.");
+ return JNI_FALSE;
+ }
+
+ sGpsNavigationMessageInterface->close();
+ return JNI_TRUE;
+}
+
static JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
@@ -1336,7 +1448,16 @@ static JNINativeMethod sMethods[] = {
(void*) android_location_GpsLocationProvider_start_measurement_collection},
{"native_stop_measurement_collection",
"()Z",
- (void*) android_location_GpsLocationProvider_stop_measurement_collection}
+ (void*) android_location_GpsLocationProvider_stop_measurement_collection},
+ {"native_is_navigation_message_supported",
+ "()Z",
+ (void*) android_location_GpsLocationProvider_is_navigation_message_supported},
+ {"native_start_navigation_message_collection",
+ "()Z",
+ (void*) android_location_GpsLocationProvider_start_navigation_message_collection},
+ {"native_stop_navigation_message_collection",
+ "()Z",
+ (void*) android_location_GpsLocationProvider_stop_navigation_message_collection},
};
int register_android_server_location_GpsLocationProvider(JNIEnv* env)
diff --git a/services/tests/servicestests/src/com/android/server/task/TaskStoreTest.java b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
index cb8da707b809..2b693a31408e 100644
--- a/services/tests/servicestests/src/com/android/server/task/TaskStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/JobStoreTest.java
@@ -1,4 +1,4 @@
-package com.android.server.task;
+package com.android.server.job;
import android.content.ComponentName;
@@ -9,40 +9,32 @@ import android.os.PersistableBundle;
import android.test.AndroidTestCase;
import android.test.RenamingDelegatingContext;
import android.util.Log;
+import android.util.ArraySet;
-import com.android.server.job.JobMapReadFinishedListener;
-import com.android.server.job.JobStore;
import com.android.server.job.controllers.JobStatus;
-import java.util.List;
+import java.util.Iterator;
/**
* Test reading and writing correctly from file.
*/
-public class TaskStoreTest extends AndroidTestCase {
+public class JobStoreTest extends AndroidTestCase {
private static final String TAG = "TaskStoreTest";
private static final String TEST_PREFIX = "_test_";
- // private static final int USER_NON_0 = 3;
+
private static final int SOME_UID = 34234;
private ComponentName mComponent;
- private static final long IO_WAIT = 600L;
+ private static final long IO_WAIT = 1000L;
JobStore mTaskStoreUnderTest;
Context mTestContext;
- JobMapReadFinishedListener mTaskMapReadFinishedListenerStub =
- new JobMapReadFinishedListener() {
- @Override
- public void onJobMapReadFinished(List<JobStatus> tasks) {
- // do nothing.
- }
- };
@Override
public void setUp() throws Exception {
mTestContext = new RenamingDelegatingContext(getContext(), TEST_PREFIX);
Log.d(TAG, "Saving tasks to '" + mTestContext.getFilesDir() + "'");
- mTaskStoreUnderTest = JobStore.initAndGetForTesting(mTestContext,
- mTestContext.getFilesDir(), mTaskMapReadFinishedListenerStub);
+ mTaskStoreUnderTest =
+ JobStore.initAndGetForTesting(mTestContext, mTestContext.getFilesDir());
mComponent = new ComponentName(getContext().getPackageName(), StubClass.class.getName());
}
@@ -69,19 +61,17 @@ public class TaskStoreTest extends AndroidTestCase {
mTaskStoreUnderTest.add(ts);
Thread.sleep(IO_WAIT);
// Manually load tasks from xml file.
- mTaskStoreUnderTest.readJobMapFromDisk(new JobMapReadFinishedListener() {
- @Override
- public void onJobMapReadFinished(List<JobStatus> tasks) {
- assertEquals("Didn't get expected number of persisted tasks.", 1, tasks.size());
- JobStatus loadedTaskStatus = tasks.get(0);
- assertTasksEqual(task, loadedTaskStatus.getJob());
- assertEquals("Different uids.", SOME_UID, tasks.get(0).getUid());
- compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
- ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
- compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
- ts.getLatestRunTimeElapsed(), loadedTaskStatus.getLatestRunTimeElapsed());
- }
- });
+ final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
+
+ assertEquals("Didn't get expected number of persisted tasks.", 1, jobStatusSet.size());
+ final JobStatus loadedTaskStatus = jobStatusSet.iterator().next();
+ assertTasksEqual(task, loadedTaskStatus.getJob());
+ assertEquals("Different uids.", SOME_UID, loadedTaskStatus.getUid());
+ compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
+ ts.getEarliestRunTime(), loadedTaskStatus.getEarliestRunTime());
+ compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
+ ts.getLatestRunTimeElapsed(), loadedTaskStatus.getLatestRunTimeElapsed());
}
@@ -104,26 +94,25 @@ public class TaskStoreTest extends AndroidTestCase {
mTaskStoreUnderTest.add(taskStatus1);
mTaskStoreUnderTest.add(taskStatus2);
Thread.sleep(IO_WAIT);
- mTaskStoreUnderTest.readJobMapFromDisk(new JobMapReadFinishedListener() {
- @Override
- public void onJobMapReadFinished(List<JobStatus> tasks) {
- assertEquals("Incorrect # of persisted tasks.", 2, tasks.size());
- JobStatus loaded1 = tasks.get(0);
- JobStatus loaded2 = tasks.get(1);
- assertTasksEqual(task1, loaded1.getJob());
- assertTasksEqual(task2, loaded2.getJob());
-
- // Check that the loaded task has the correct runtimes.
- compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
- taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime());
- compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
- taskStatus1.getLatestRunTimeElapsed(), loaded1.getLatestRunTimeElapsed());
- compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
- taskStatus2.getEarliestRunTime(), loaded2.getEarliestRunTime());
- compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
- taskStatus2.getLatestRunTimeElapsed(), loaded2.getLatestRunTimeElapsed());
- }
- });
+
+ final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
+ assertEquals("Incorrect # of persisted tasks.", 2, jobStatusSet.size());
+ Iterator<JobStatus> it = jobStatusSet.iterator();
+ JobStatus loaded1 = it.next();
+ JobStatus loaded2 = it.next();
+ assertTasksEqual(task1, loaded1.getJob());
+ assertTasksEqual(task2, loaded2.getJob());
+
+ // Check that the loaded task has the correct runtimes.
+ compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
+ taskStatus1.getEarliestRunTime(), loaded1.getEarliestRunTime());
+ compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
+ taskStatus1.getLatestRunTimeElapsed(), loaded1.getLatestRunTimeElapsed());
+ compareTimestampsSubjectToIoLatency("Early run-times not the same after read.",
+ taskStatus2.getEarliestRunTime(), loaded2.getEarliestRunTime());
+ compareTimestampsSubjectToIoLatency("Late run-times not the same after read.",
+ taskStatus2.getLatestRunTimeElapsed(), loaded2.getLatestRunTimeElapsed());
}
@@ -144,15 +133,12 @@ public class TaskStoreTest extends AndroidTestCase {
mTaskStoreUnderTest.add(taskStatus);
Thread.sleep(IO_WAIT);
- mTaskStoreUnderTest.readJobMapFromDisk(new JobMapReadFinishedListener() {
- @Override
- public void onJobMapReadFinished(List<JobStatus> tasks) {
- assertEquals("Incorrect # of persisted tasks.", 1, tasks.size());
- JobStatus loaded = tasks.get(0);
- assertTasksEqual(task, loaded.getJob());
- }
- });
+ final ArraySet<JobStatus> jobStatusSet = new ArraySet<JobStatus>();
+ mTaskStoreUnderTest.readJobMapFromDisk(jobStatusSet);
+ assertEquals("Incorrect # of persisted tasks.", 1, jobStatusSet.size());
+ JobStatus loaded = jobStatusSet.iterator().next();
+ assertTasksEqual(task, loaded.getJob());
}
/**
@@ -201,4 +187,4 @@ public class TaskStoreTest extends AndroidTestCase {
private static class StubClass {}
-} \ No newline at end of file
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 9cff7657289c..2555874ac9b0 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -20,6 +20,7 @@ import android.annotation.SystemApi;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
+import android.content.Intent;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -2980,6 +2981,19 @@ public class TelephonyManager {
/** @hide */
@SystemApi
+ public List<String> getCarrierPackageNamesForBroadcastIntent(Intent intent) {
+ try {
+ return getITelephony().getCarrierPackageNamesForBroadcastIntent(intent);
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getCarrierPackageNamesForBroadcastIntent RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "getCarrierPackageNamesForBroadcastIntent NPE", ex);
+ }
+ return null;
+ }
+
+ /** @hide */
+ @SystemApi
public void dial(String number) {
try {
getITelephony().dial(number);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 435c3341b5a9..ec7b8ae71227 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telephony;
+import android.content.Intent;
import android.os.Bundle;
import java.util.List;
import android.telephony.NeighboringCellInfo;
@@ -660,6 +661,17 @@ interface ITelephony {
int checkCarrierPrivilegesForPackage(String pkgname);
/**
+ * Returns the package name of the carrier apps that should handle the input intent.
+ *
+ * @param packageManager PackageManager for getting receivers.
+ * @param intent Intent that will be broadcast.
+ * @return list of carrier app package names that can handle the intent.
+ * Returns null if there is an error and an empty list if there
+ * are no matching packages.
+ */
+ List<String> getCarrierPackageNamesForBroadcastIntent(in Intent intent);
+
+ /**
* Set whether Android should display a simplified Mobile Network Settings UI.
* The setting won't be persisted during power cycle.
*
diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml
index a16b74901355..ee62e5ee9faa 100644
--- a/tests/VectorDrawableTest/AndroidManifest.xml
+++ b/tests/VectorDrawableTest/AndroidManifest.xml
@@ -100,7 +100,7 @@
</activity>
<activity
android:name="VectorDrawableStaticPerf"
- android:label="Performance of vector images" >
+ android:label="System icons" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 66a9452d5380..3b01e029e1c7 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -26,7 +26,7 @@
<group>
<path
android:name="box1"
- android:pathData="m20,200l100,90l180,-180l-35,-35l-145,145l-60,-60l-40,40z"
+ android:pathData="m20,200l100,90l180-180l-35-35l-145,145l-60-60l-40,40z"
android:fill="?android:attr/colorControlActivated"
android:stroke="?android:attr/colorControlActivated"
android:strokeLineCap="round"
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
index 2fdb6769693a..cd2fd479098d 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable03.xml
@@ -35,16 +35,16 @@
M 0, 6.125
l 7.3, 0
l 0, 12.25
- l -7.3, 0
+ l-7.3, 0
z" />
</group>
<group>
<path
android:name="one"
android:fill="#ff88ff"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
- l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
- l -5.046875,0.0 0.0,-1.0Z" />
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
+ l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l-5.046875,0.0 0.0-1.0Z" />
</group>
<group
android:pivotX="3.65"
@@ -57,22 +57,22 @@
M 0, 0
l 7.3, 0
l 0, 6.125
- l -7.3, 0
+ l-7.3, 0
z" />
</group>
<group>
<path
android:name="two"
android:fill="#ff88ff"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z" />
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+ q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
+ q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
+ q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875
+ q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875
+ q 0.625-0.15625 1.140625-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625
+ q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375
+ q-0.78125024,0.8125-2.2187502,2.265625Z" />
</group>
</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
index 296e026116e7..d57ae8b756ef 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable04.xml
@@ -28,41 +28,41 @@
android:name="clip1"
android:pathData="
M 3.65, 6.125
- m -.001, 0
+ m-.001, 0
a .001,.001 0 1,0 .002,0
- a .001,.001 0 1,0 -.002,0z"
+ a .001,.001 0 1,0-.002,0z"
android:clipToPath="true"
android:fill="#112233"
/>
<path
android:name="one"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
- l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
- l -5.046875,0.0 0.0,-1.0Z"
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
+ l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l-5.046875,0.0 0.0-1.0Z"
android:fill="#ff88ff"
/>
<path
android:name="clip2"
android:pathData="
M 3.65, 6.125
- m -6, 0
+ m-6, 0
a 6,6 0 1,0 12,0
- a 6,6 0 1,0 -12,0z"
+ a 6,6 0 1,0-12,0z"
android:clipToPath="true"
android:fill="#112233"
/>
<path
android:name="two"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z"
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+ q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
+ q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
+ q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875
+ q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875
+ q 0.625-0.15625 1.140625-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625
+ q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375
+ q-0.78125024,0.8125-2.2187502,2.265625Z"
android:fill="#ff88ff"
/>
</group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
index 1633326ae2b0..673c46524243 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
@@ -28,21 +28,21 @@
<path
android:name="one"
android:fill="#ffff00"
- android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
- l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
- l -5.046875,0.0 0.0,-1.0Z" />
+ android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0-6.671875-2.109375,0.421875 0.0-1.078125
+ l 2.09375-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
+ l-5.046875,0.0 0.0-1.0Z" />
<path
android:name="two"
android:fill="#ffff00"
android:fillOpacity="0"
- android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
- q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
- q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
- q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
- q -0.609375,0.1875 -1.3125,0.59375l 0.0,-1.203125q 0.71875,-0.28125 1.328125,-0.421875
- q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
- q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
- q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
- q -0.78125024,0.8125 -2.2187502,2.265625Z" />
+ android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0-5.5625,0.0 0.0-1.0q 0.671875-0.6875 1.828125-1.859375
+ q 1.1718752-1.1875 1.4687502-1.53125 0.578125-0.625 0.796875-1.0625
+ q 0.234375-0.453125 0.234375-0.875 0.0-0.703125-0.5-1.140625
+ q-0.484375-0.4375-1.2656252-0.4375-0.5625,0.0-1.1875,0.1875
+ q-0.609375,0.1875-1.3125,0.59375l 0.0-1.203125q 0.71875-0.28125 1.328125-0.421875
+ q 0.625-0.15625 1.140625-0.15625 1.3593752,0.0 2.1718752,0.6875
+ q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125-0.203125,1.015625
+ q-0.203125,0.484375-0.734375,1.140625-0.15625,0.171875-0.9375,0.984375
+ q-0.78125024,0.8125-2.2187502,2.265625Z" />
</group>
</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
index 7c7e679a3d1e..ccb0df0c9aa8 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable07.xml
@@ -23,9 +23,9 @@
<group>
<path
android:name="back"
- android:pathData="M 20,55 l 35.3,-35.3 7.07,7.07 -35.3,35.3 z
- M 27,50 l 97,0 0,10 -97,0 z
- M 20,55 l 7.07,-7.07 35.3,35.3 -7.07,7.07 z"
+ android:pathData="M 20,55 l 35.3-35.3 7.07,7.07-35.3,35.3 z
+ M 27,50 l 97,0 0,10-97,0 z
+ M 20,55 l 7.07-7.07 35.3,35.3-7.07,7.07 z"
android:fill="#ffffffff"
/>
</group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
index c93c85fef3bd..77434fca58f0 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
@@ -30,7 +30,7 @@
<path
android:name="house"
android:fill="#ffffffff"
- android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z"/>
+ android:pathData="M 100,20 l 0,0 0,140-80,0 z M 100,20 l 0,0 80,140-80,0 z"/>
</group>
</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
index 8484e9e2f107..df24713e3ba0 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
@@ -28,19 +28,19 @@
<path
android:name="bar3"
android:fill="#FFFFFFFF"
- android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
+ android:pathData="M49.001,60c-5.466,0-9.899,4.478-9.899,10s4.434,10,9.899,10c5.468,0,9.899-4.478,9.899-10S54.469,60,49.001,60z" />
<path
android:name="bar2"
android:fill="#FFFFFFFF"
- android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
+ android:pathData="M28.001,48.787l7,7.07c7.731-7.811,20.269-7.81,28.001,0l6.999-7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
<path
android:name="bar1"
android:fill="#FF555555"
- android:pathData="M14.001,34.645 L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
+ android:pathData="M14.001,34.645 L21,41.716c15.464-15.621,40.536-15.621,56,0l7.001-7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
<path
android:name="bar0"
android:fill="#FF555555"
- android:pathData="M0,20.502l6.999,7.071 c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
+ android:pathData="M0,20.502l6.999,7.071 c23.196-23.431,60.806-23.431,84.002,0L98,20.503C70.938-6.834,27.063-6.834,0,20.502z" />
</group>
</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml
index c8840f56a6b9..5a66e2d4bc9f 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable_favorite.xml
@@ -32,11 +32,11 @@
android:fill="#ff000000"
android:pathData="M2.100006104,-6
C0.1449127197,-6,1.600006104,-5.975006104,0,-5.975006104
- C-1.574996948,-5.975006104,0.00309753418,-6,-1.949996948,-6
+ C-1.574996948,-5.975006104,0.00309753418,-6-1.949996948-6
C-4.492996216,-6,-5.949996948,-3.718399048,-5.949996948,-1.149993896
C-5.949996948,2.379302979,-5.699996948,5.100006104,0,5.100006104
C5.699996948,5.100006104,6,2.379302979,6,-1.149993896
- C6,-3.718399048,4.643005371,-6,2.100006104,-6" />
+ C6,-3.718399048,4.643005371-6,2.100006104-6" />
</group>
</vector> \ No newline at end of file