Merge "Fix Tethering Notifications for multiple ifaces"
diff --git a/api/current.xml b/api/current.xml
index e982dfcb..64f0c23 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -11732,6 +11732,17 @@
visibility="public"
>
</field>
+<field name="custom"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16908331"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="cut"
type="int"
transient="false"
@@ -80529,6 +80540,17 @@
visibility="public"
>
</method>
+<method name="isBluetoothScoAvailableOffCall"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="isBluetoothScoOn"
return="boolean"
abstract="false"
@@ -80849,6 +80871,28 @@
<parameter name="vibrateType" type="int">
</parameter>
</method>
+<method name="startBluetoothSco"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="stopBluetoothSco"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
<method name="unloadSoundEffects"
return="void"
abstract="false"
@@ -80884,6 +80928,17 @@
visibility="public"
>
</field>
+<field name="ACTION_SCO_AUDIO_STATE_CHANGED"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.SCO_AUDIO_STATE_CHANGED""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="ADJUST_LOWER"
type="int"
transient="false"
@@ -80994,6 +81049,17 @@
visibility="public"
>
</field>
+<field name="EXTRA_SCO_AUDIO_STATE"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value=""android.media.extra.SCO_AUDIO_STATE""
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="EXTRA_VIBRATE_SETTING"
type="java.lang.String"
transient="false"
@@ -81357,6 +81423,39 @@
visibility="public"
>
</field>
+<field name="SCO_AUDIO_STATE_CONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCO_AUDIO_STATE_DISCONNECTED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="0"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="SCO_AUDIO_STATE_ERROR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-1"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
<field name="STREAM_ALARM"
type="int"
transient="false"
@@ -121973,7 +122072,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="message" type="java.lang.String">
+<parameter name="text" type="java.lang.String">
</parameter>
</method>
</class>
@@ -385574,7 +385673,7 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="message" type="java.lang.String">
+<parameter name="text" type="java.lang.String">
</parameter>
</method>
</class>
diff --git a/cmds/rawbu/backup.cpp b/cmds/rawbu/backup.cpp
index 394ce41..c4fa765 100644
--- a/cmds/rawbu/backup.cpp
+++ b/cmds/rawbu/backup.cpp
@@ -318,7 +318,7 @@
result = 0;
goto done;
}
- } else {
+ } else if (S_ISREG(statBuffer.st_mode)) {
printf("Saving file %s...\n", fullPath);
if (write_header(fh, TYPE_FILE, fullPath, &statBuffer) == 0) {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 1c980e3..fa6abec 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3908,16 +3908,16 @@
}
}
- final void applyConfigurationToResourcesLocked(Configuration config) {
+ final boolean applyConfigurationToResourcesLocked(Configuration config) {
if (mResConfiguration == null) {
mResConfiguration = new Configuration();
}
if (!mResConfiguration.isOtherSeqNewer(config)) {
if (DEBUG_CONFIGURATION) Log.v(TAG, "Skipping new config: curSeq="
+ mResConfiguration.seq + ", newSeq=" + config.seq);
- return;
+ return false;
}
- mResConfiguration.updateFrom(config);
+ int changes = mResConfiguration.updateFrom(config);
DisplayMetrics dm = getDisplayMetricsLocked(true);
// set it for java, this also affects newly created Resources
@@ -3948,6 +3948,8 @@
it.remove();
}
}
+
+ return changes != 0;
}
final void handleConfigurationChanged(Configuration config) {
@@ -4522,17 +4524,20 @@
ViewRoot.addConfigCallback(new ComponentCallbacks() {
public void onConfigurationChanged(Configuration newConfig) {
synchronized (mPackages) {
- if (mPendingConfiguration == null ||
- mPendingConfiguration.isOtherSeqNewer(newConfig)) {
- mPendingConfiguration = newConfig;
-
- // We need to apply this change to the resources
- // immediately, because upon returning the view
- // hierarchy will be informed about it.
- applyConfigurationToResourcesLocked(newConfig);
+ // We need to apply this change to the resources
+ // immediately, because upon returning the view
+ // hierarchy will be informed about it.
+ if (applyConfigurationToResourcesLocked(newConfig)) {
+ // This actually changed the resources! Tell
+ // everyone about it.
+ if (mPendingConfiguration == null ||
+ mPendingConfiguration.isOtherSeqNewer(newConfig)) {
+ mPendingConfiguration = newConfig;
+
+ queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
+ }
}
}
- queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
public void onLowMemory() {
}
diff --git a/core/java/android/app/AlertDialog.java b/core/java/android/app/AlertDialog.java
index 2603579..2714de5 100644
--- a/core/java/android/app/AlertDialog.java
+++ b/core/java/android/app/AlertDialog.java
@@ -35,12 +35,12 @@
/**
* A subclass of Dialog that can display one, two or three buttons. If you only want to
* display a String in this dialog box, use the setMessage() method. If you
- * want to display a more complex view, look up the FrameLayout called "body"
+ * want to display a more complex view, look up the FrameLayout called "custom"
* and add your view to it:
*
* <pre>
- * FrameLayout fl = (FrameLayout) findViewById(R.id.body);
- * fl.add(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
+ * FrameLayout fl = (FrameLayout) findViewById(android.R.id.custom);
+ * fl.addView(myView, new LayoutParams(MATCH_PARENT, WRAP_CONTENT));
* </pre>
*
* <p>The AlertDialog class takes care of automatically setting
diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java
index e9a9f31..af327c3 100644
--- a/core/java/android/content/pm/PackageInfo.java
+++ b/core/java/android/content/pm/PackageInfo.java
@@ -153,6 +153,12 @@
* the {@link android.R.attr#installLocation} attribute.
* @hide
*/
+ public static final int INSTALL_LOCATION_UNSPECIFIED = -1;
+ /**
+ * Constant corresponding to <code>auto</code> in
+ * the {@link android.R.attr#installLocation} attribute.
+ * @hide
+ */
public static final int INSTALL_LOCATION_AUTO = 0;
/**
* Constant corresponding to <code>internalOnly</code> in
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index c33f305..3be4cebd 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -96,7 +96,8 @@
private static final Object mSync = new Object();
private static WeakReference<byte[]> mReadBuffer;
- private static boolean sCompatibilityModeEnabled = true;
+ private static boolean sCompatibilityModeEnabled = true;
+ private static final int PARSE_DEFAULT_INSTALL_LOCATION = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
static class ParsePackageItemArgs {
final Package owner;
@@ -352,6 +353,7 @@
public final static int PARSE_IGNORE_PROCESSES = 1<<3;
public final static int PARSE_FORWARD_LOCK = 1<<4;
public final static int PARSE_ON_SDCARD = 1<<5;
+ public final static int PARSE_IS_SYSTEM_DIR = 1<<6;
public int getParseError() {
return mParseError;
@@ -707,12 +709,12 @@
+ pkgName + "\": " + nameError;
return null;
}
- int installLocation = PackageInfo.INSTALL_LOCATION_AUTO;
+ int installLocation = PARSE_DEFAULT_INSTALL_LOCATION;
for (int i = 0; i < attrs.getAttributeCount(); i++) {
String attr = attrs.getAttributeName(i);
if (attr.equals("installLocation")) {
installLocation = attrs.getAttributeIntValue(i,
- PackageInfo.INSTALL_LOCATION_AUTO);
+ PARSE_DEFAULT_INSTALL_LOCATION);
break;
}
}
@@ -778,7 +780,7 @@
pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation,
- PackageInfo.INSTALL_LOCATION_AUTO);
+ PARSE_DEFAULT_INSTALL_LOCATION);
// Resource boolean are -1, so 1 means we don't know the value.
int supportsSmallScreens = 1;
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index afe4191..1254782 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -167,11 +167,15 @@
/**
* Start Wifi Access Point
*/
- void startAccessPoint(in WifiConfiguration wifiConfig, String intf);
+ void startAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
/**
* Stop Wifi Access Point
*/
void stopAccessPoint();
+ /**
+ * Set Access Point config
+ */
+ void setAccessPoint(in WifiConfiguration wifiConfig, String wlanIface, String softapIface);
}
diff --git a/core/java/android/pim/vcard/VCardEntry.java b/core/java/android/pim/vcard/VCardEntry.java
index 61012c9..e40a7ba 100644
--- a/core/java/android/pim/vcard/VCardEntry.java
+++ b/core/java/android/pim/vcard/VCardEntry.java
@@ -1055,6 +1055,8 @@
public Uri pushIntoContentResolver(ContentResolver resolver) {
ArrayList<ContentProviderOperation> operationList =
new ArrayList<ContentProviderOperation>();
+ // After applying the batch the first result's Uri is returned so it is important that
+ // the RawContact is the first operation that gets inserted into the list
ContentProviderOperation.Builder builder =
ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
String myGroupsId = null;
@@ -1290,8 +1292,11 @@
ContentProviderResult[] results = resolver.applyBatch(
ContactsContract.AUTHORITY, operationList);
// the first result is always the raw_contact. return it's uri so
- // that it can be found later
- return results[0].uri;
+ // that it can be found later. do null checking for badly behaving
+ // ContentResolvers
+ return (results == null || results.length == 0 || results[0] == null)
+ ? null
+ : results[0].uri;
} catch (RemoteException e) {
Log.e(LOG_TAG, String.format("%s: %s", e.toString(), e.getMessage()));
return null;
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 837ce91..726793d 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -24,7 +24,6 @@
import android.os.Handler;
import android.os.Message;
import android.view.View;
-import android.view.Window;
/**
* Shows a hierarchy of {@link Preference} objects as
@@ -81,6 +80,8 @@
private PreferenceManager mPreferenceManager;
+ private Bundle mSavedInstanceState;
+
/**
* The starting request code given out to preference framework.
*/
@@ -137,15 +138,19 @@
@Override
protected void onRestoreInstanceState(Bundle state) {
- super.onRestoreInstanceState(state);
-
Bundle container = state.getBundle(PREFERENCES_TAG);
if (container != null) {
final PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
preferenceScreen.restoreHierarchyState(container);
+ mSavedInstanceState = state;
+ return;
}
}
+
+ // Only call this if we didn't save the instance state for later.
+ // If we did save it, it will be restored when we bind the adapter.
+ super.onRestoreInstanceState(state);
}
@Override
@@ -176,6 +181,10 @@
final PreferenceScreen preferenceScreen = getPreferenceScreen();
if (preferenceScreen != null) {
preferenceScreen.bind(getListView());
+ if (mSavedInstanceState != null) {
+ super.onRestoreInstanceState(mSavedInstanceState);
+ mSavedInstanceState = null;
+ }
}
}
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index dda9018..1d27828 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -870,6 +870,13 @@
public static final String ARTIST = "artist";
/**
+ * The artist credited for the album that contains the audio file
+ * <P>Type: TEXT</P>
+ * @hide
+ */
+ public static final String ALBUM_ARTIST = "album_artist";
+
+ /**
* A non human readable key calculated from the ARTIST, used for
* searching, sorting and grouping
* <P>Type: TEXT</P>
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index d8010bcc..53c238c 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -124,6 +124,13 @@
}
};
+ final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
+ = new ViewTreeObserver.OnScrollChangedListener() {
+ public void onScrollChanged() {
+ updateWindow(false);
+ }
+ };
+
boolean mRequestedVisible = false;
boolean mWindowVisibility = false;
boolean mViewVisibility = false;
@@ -180,6 +187,7 @@
mLayout.token = getWindowToken();
mLayout.setTitle("SurfaceView");
mViewVisibility = getVisibility() == VISIBLE;
+ getViewTreeObserver().addOnScrollChangedListener(mScrollChangedListener);
}
@Override
@@ -200,6 +208,7 @@
@Override
protected void onDetachedFromWindow() {
+ getViewTreeObserver().removeOnScrollChangedListener(mScrollChangedListener);
mRequestedVisible = false;
updateWindow(false);
mHaveFrame = false;
@@ -224,12 +233,6 @@
}
@Override
- protected void onScrollChanged(int l, int t, int oldl, int oldt) {
- super.onScrollChanged(l, t, oldl, oldt);
- updateWindow(false);
- }
-
- @Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
updateWindow(false);
diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java
index 1c17575..6216603 100644
--- a/core/java/android/webkit/HttpAuthHandler.java
+++ b/core/java/android/webkit/HttpAuthHandler.java
@@ -19,6 +19,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.util.Log;
import java.util.ListIterator;
import java.util.LinkedList;
@@ -52,6 +53,14 @@
private static final int AUTH_PROCEED = 100;
private static final int AUTH_CANCEL = 200;
+ // Use to synchronize when making synchronous calls to
+ // onReceivedHttpAuthRequest(). We can't use a single Boolean object for
+ // both the lock and the state, because Boolean is immutable.
+ Object mRequestInFlightLock = new Object();
+ boolean mRequestInFlight;
+ String mUsername;
+ String mPassword;
+
/**
* Creates a new HTTP authentication handler with an empty
* loader queue
@@ -70,6 +79,7 @@
synchronized (mLoaderQueue) {
loader = mLoaderQueue.poll();
}
+ assert(loader.isSynchronous() == false);
switch (msg.what) {
case AUTH_PROCEED:
@@ -87,25 +97,70 @@
processNextLoader();
}
+ /**
+ * Helper method used to unblock handleAuthRequest(), which in the case of a
+ * synchronous request will wait for proxy.onReceivedHttpAuthRequest() to
+ * call back to either proceed() or cancel().
+ *
+ * @param username The username to use for authentication
+ * @param password The password to use for authentication
+ * @return True if the request is synchronous and handleAuthRequest() has
+ * been unblocked
+ */
+ private boolean handleResponseForSynchronousRequest(String username, String password) {
+ LoadListener loader = null;
+ synchronized (mLoaderQueue) {
+ loader = mLoaderQueue.peek();
+ }
+ if (loader.isSynchronous()) {
+ mUsername = username;
+ mPassword = password;
+ return true;
+ }
+ return false;
+ }
+
+ private void signalRequestComplete() {
+ synchronized (mRequestInFlightLock) {
+ assert(mRequestInFlight);
+ mRequestInFlight = false;
+ mRequestInFlightLock.notify();
+ }
+ }
/**
* Proceed with the authorization with the given credentials
*
+ * May be called on the UI thread, rather than the WebCore thread.
+ *
* @param username The username to use for authentication
* @param password The password to use for authentication
*/
public void proceed(String username, String password) {
+ if (handleResponseForSynchronousRequest(username, password)) {
+ signalRequestComplete();
+ return;
+ }
Message msg = obtainMessage(AUTH_PROCEED);
msg.getData().putString("username", username);
msg.getData().putString("password", password);
sendMessage(msg);
+ signalRequestComplete();
}
/**
* Cancel the authorization request
+ *
+ * May be called on the UI thread, rather than the WebCore thread.
+ *
*/
public void cancel() {
+ if (handleResponseForSynchronousRequest(null, null)) {
+ signalRequestComplete();
+ return;
+ }
sendMessage(obtainMessage(AUTH_CANCEL));
+ signalRequestComplete();
}
/**
@@ -132,6 +187,34 @@
* authentication request
*/
/* package */ void handleAuthRequest(LoadListener loader) {
+ // The call to proxy.onReceivedHttpAuthRequest() may be asynchronous. If
+ // the request is synchronous, we must block here until we have a
+ // response.
+ if (loader.isSynchronous()) {
+ // If there's a request in flight, wait for it to complete. The
+ // response will queue a message on this thread.
+ waitForRequestToComplete();
+ // Make a request to the proxy for this request, jumping the queue.
+ // We use the queue so that the loader is present in
+ // useHttpAuthUsernamePassword().
+ synchronized (mLoaderQueue) {
+ mLoaderQueue.addFirst(loader);
+ }
+ processNextLoader();
+ // Wait for this request to complete.
+ waitForRequestToComplete();
+ // Pop the loader from the queue.
+ synchronized (mLoaderQueue) {
+ assert(mLoaderQueue.peek() == loader);
+ mLoaderQueue.poll();
+ }
+ // Call back.
+ loader.handleAuthResponse(mUsername, mPassword);
+ // The message queued by the response from the last asynchronous
+ // request, if present, will start the next request.
+ return;
+ }
+
boolean processNext = false;
synchronized (mLoaderQueue) {
@@ -146,6 +229,21 @@
}
/**
+ * Wait for the request in flight, if any, to complete
+ */
+ private void waitForRequestToComplete() {
+ synchronized (mRequestInFlightLock) {
+ while (mRequestInFlight) {
+ try {
+ mRequestInFlightLock.wait();
+ } catch(InterruptedException e) {
+ Log.e(LOGTAG, "Interrupted while waiting for request to complete");
+ }
+ }
+ }
+ }
+
+ /**
* Process the next loader in the queue (helper method)
*/
private void processNextLoader() {
@@ -154,6 +252,11 @@
loader = mLoaderQueue.peek();
}
if (loader != null) {
+ synchronized (mRequestInFlightLock) {
+ assert(mRequestInFlight == false);
+ mRequestInFlight = true;
+ }
+
CallbackProxy proxy = loader.getFrame().getCallbackProxy();
String hostname = loader.proxyAuthenticate() ?
diff --git a/core/java/android/webkit/ViewManager.java b/core/java/android/webkit/ViewManager.java
index 4e0e081..fc5c425 100644
--- a/core/java/android/webkit/ViewManager.java
+++ b/core/java/android/webkit/ViewManager.java
@@ -18,6 +18,7 @@
import android.view.SurfaceView;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.AbsoluteLayout;
import java.util.ArrayList;
@@ -155,17 +156,18 @@
v.isFixedSize = true;
}
- AbsoluteLayout.LayoutParams lp =
- (AbsoluteLayout.LayoutParams) v.mView.getLayoutParams();
+ AbsoluteLayout.LayoutParams lp;
+ ViewGroup.LayoutParams layoutParams = v.mView.getLayoutParams();
- if (lp == null)
- lp = new AbsoluteLayout.LayoutParams(ctvD(v.width), ctvD(v.height),
- ctvX(v.x), ctvY(v.y));
- else {
+ if (layoutParams instanceof AbsoluteLayout.LayoutParams) {
+ lp = (AbsoluteLayout.LayoutParams) layoutParams;
lp.width = ctvD(v.width);
lp.height = ctvD(v.height);
lp.x = ctvX(v.x);
lp.y = ctvY(v.y);
+ } else {
+ lp = new AbsoluteLayout.LayoutParams(ctvD(v.width), ctvD(v.height),
+ ctvX(v.x), ctvY(v.y));
}
return lp;
}
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index ded0559..531d9fe 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -64,6 +64,7 @@
private static final int STATE_PLAYBACK_COMPLETED = 5;
private static final int STATE_SUSPEND = 6;
private static final int STATE_RESUME = 7;
+ private static final int STATE_SUSPEND_UNSUPPORTED = 8;
// mCurrentState is a VideoView object's current state.
// mTargetState is the state that a method caller intends to reach.
@@ -586,8 +587,9 @@
mCurrentState = STATE_SUSPEND;
mTargetState = STATE_SUSPEND;
} else {
- Log.w(TAG, "Unable to suspend video");
- mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
+ release(false);
+ mCurrentState = STATE_SUSPEND_UNSUPPORTED;
+ Log.w(TAG, "Unable to suspend video. Release MediaPlayer.");
}
}
}
@@ -603,8 +605,11 @@
mTargetState = mStateWhenSuspended;
} else {
Log.w(TAG, "Unable to resume video");
- mErrorListener.onError(mMediaPlayer, MediaPlayer.MEDIA_ERROR_UNKNOWN, 0);
}
+ return;
+ }
+ if (mCurrentState == STATE_SUSPEND_UNSUPPORTED) {
+ openVideo();
}
}
diff --git a/core/java/com/android/internal/util/HierarchicalState.java b/core/java/com/android/internal/util/HierarchicalState.java
index 002338a..b37f46c 100644
--- a/core/java/com/android/internal/util/HierarchicalState.java
+++ b/core/java/com/android/internal/util/HierarchicalState.java
@@ -21,10 +21,9 @@
/**
* {@hide}
*
- * The abstract class for implementing states in a
- * HierarchicalStateMachine and HandlerStateMachine.
+ * The class for implementing states in a HierarchicalStateMachine
*/
-public abstract class HierarchicalState {
+public class HierarchicalState {
/**
* Constructor
@@ -54,7 +53,9 @@
* if the parent state's processMessage should
* be invoked.
*/
- abstract protected boolean processMessage(Message msg);
+ protected boolean processMessage(Message msg) {
+ return false;
+ }
/**
* Called when a state is exited.
diff --git a/core/java/com/android/internal/util/HierarchicalStateMachine.java b/core/java/com/android/internal/util/HierarchicalStateMachine.java
index 7d7f130..9911f48 100644
--- a/core/java/com/android/internal/util/HierarchicalStateMachine.java
+++ b/core/java/com/android/internal/util/HierarchicalStateMachine.java
@@ -574,23 +574,41 @@
}
/**
- * Process the message abiding by the hierarchical semantics.
+ * Process the message abiding by the hierarchical semantics
+ * and perform any requested transitions.
*/
processMsg(msg);
+ performTransitions();
+ if (mDbg) Log.d(TAG, "handleMessage: X");
+ }
+
+ /**
+ * Do any transitions
+ */
+ private void performTransitions() {
/**
* If transitionTo has been called, exit and then enter
- * the appropriate states.
+ * the appropriate states. We loop on this to allow
+ * enter and exit methods to use transitionTo.
*/
- if (mDestState != null) {
+ HierarchicalState destState = null;
+ while (mDestState != null) {
if (mDbg) Log.d(TAG, "handleMessage: new destination call exit");
/**
+ * Save mDestState locally and set to null
+ * to know if enter/exit use transitionTo.
+ */
+ destState = mDestState;
+ mDestState = null;
+
+ /**
* Determine the states to exit and enter and return the
* common ancestor state of the enter/exit states. Then
* invoke the exit methods then the enter methods.
*/
- StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(mDestState);
+ StateInfo commonStateInfo = setupTempStateStackWithStatesToEnter(destState);
invokeExitMethods(commonStateInfo);
int stateStackEnteringIndex = moveTempStateStackToStateStack();
invokeEnterMethods(stateStackEnteringIndex);
@@ -603,25 +621,31 @@
* message queue.
*/
moveDeferredMessageAtFrontOfQueue();
+ }
- /**
- * Call halting() if we've transitioned to the halting
- * state. All subsequent messages will be processed in
- * in the halting state which invokes haltedProcessMessage(msg);
- */
- if (mDestState == mQuittingState) {
+ /**
+ * After processing all transitions check and
+ * see if the last transition was to quit or halt.
+ */
+ if (destState != null) {
+ if (destState == mQuittingState) {
+ /**
+ * We are quitting so ignore all messages.
+ */
mHsm.quitting();
if (mHsm.mHsmThread != null) {
// If we made the thread then quit looper
getLooper().quit();
}
- } else if (mDestState == mHaltingState) {
+ } else if (destState == mHaltingState) {
+ /**
+ * Call halting() if we've transitioned to the halting
+ * state. All subsequent messages will be processed in
+ * in the halting state which invokes haltedProcessMessage(msg);
+ */
mHsm.halting();
}
- mDestState = null;
}
-
- if (mDbg) Log.d(TAG, "handleMessage: X");
}
/**
@@ -657,6 +681,11 @@
mIsConstructionCompleted = true;
invokeEnterMethods(0);
+ /**
+ * Perform any transitions requested by the enter methods
+ */
+ performTransitions();
+
if (mDbg) Log.d(TAG, "completeConstruction: X");
}
@@ -1167,7 +1196,6 @@
return Message.obtain(mHsmHandler, what, obj);
}
-
/**
* Enqueue a message to this state machine.
*/
diff --git a/core/jni/android_database_SQLiteDatabase.cpp b/core/jni/android_database_SQLiteDatabase.cpp
index 4e8d05b..36234a9 100644
--- a/core/jni/android_database_SQLiteDatabase.cpp
+++ b/core/jni/android_database_SQLiteDatabase.cpp
@@ -72,8 +72,9 @@
}
static void sqlLogger(void *databaseName, int iErrCode, const char *zMsg) {
- LOGI("sqlite returned: database = %s, error code = %d, msg = %s\n",
- (char *)databaseName, iErrCode, zMsg);
+ // skip printing this message if it is due to certain types of errors
+ if (iErrCode == SQLITE_CONSTRAINT) return;
+ LOGI("sqlite returned: error code = %d, msg = %s\n", iErrCode, zMsg);
}
// register the logging func on sqlite. needs to be done BEFORE any sqlite3 func is called.
diff --git a/core/res/res/values-en-rUS/donottranslate-names.xml b/core/res/res/values-en-rUS/donottranslate-names.xml
index f8ec765..aa0abe3 100644
--- a/core/res/res/values-en-rUS/donottranslate-names.xml
+++ b/core/res/res/values-en-rUS/donottranslate-names.xml
@@ -4,35 +4,51 @@
<!-- various string resources for Contacts -->
<string-array name="common_nicknames">
- <item>Abigail, Abbie, Gail, Gayle</item>
+ <item>Abigail, Abbie</item>
+ <item>Abigail, Gail, Gayle</item>
<item>Abe, Abraham</item>
- <item>Aggie, Agatha, Agnes</item>
- <item>Albert, Al, Bert, Bertie</item>
- <item>Alexander, Al, Alec, Alex, Lex, Sasha</item>
- <item>Alexandra, Al, Allie, Ally, Lex, Lexie, Sandra, Sandy, Sasha</item>
+ <item>Agatha, Aggie</item>
+ <item>Agatha, Agnes</item>
+ <item>Albert, Al</item>
+ <item>Albert, Bert, Bertie</item>
+ <item>Alexander, Al, Alex</item>
+ <item>Alexander, Al, Alec</item>
+ <item>Alexander, Alex, Lex</item>
+ <item>Alexander, Alex, Sasha</item>
+ <item>Alexandra, Al, Allie, Ally</item>
+ <item>Alexandra, Lex, Lexie</item>
+ <item>Alexandra, Sandra, Sandy</item>
+ <item>Alexandra, Sasha</item>
<item>Alf, Alfred, Alfredo, Alfie</item>
<item>Alice, Allie, Ally</item>
<item>Alison, Allie, Ally</item>
<item>Allison, Allie, Ally</item>
<item>Amanda, Mandi, Mandy</item>
<item>Andrea, Andie</item>
- <item>Andrew, Andy, Drew</item>
+ <item>Andrew, Andy</item>
+ <item>Andrew, Drew</item>
<item>Anne, Annie, Annette</item>
<item>Anthony, Tony, Toni, Tone</item>
<item>Arthur, Art, Arty</item>
- <item>Barbara, Babs, Barb, Barbie</item>
- <item>Benjamin, Ben, Benji, Benny</item>
- <item>Bernard, Bern, Bernie, Barnie</item>
+ <item>Barbara, Barb, Barbie</item>
+ <item>Benjamin, Ben, Benny</item>
+ <item>Benjamin, Benji</item>
+ <item>Bernard, Barnie</item>
+ <item>Bernard, Bern, Bernie</item>
<item>Bertram, Bert, Bertie</item>
<item>Bradly, Brad</item>
<item>Calvin, Cal</item>
<item>Catherine, Cat, Cate, Cath, Catie, Cathy, Kat, Kate, Katie, Kathy</item>
<item>Carrie, Caroline, Carolyn</item>
- <item>Charles, Chuck, Chaz, Charlie, Buck</item>
+ <item>Charles, Charlie</item>
+ <item>Charles, Chuck</item>
+ <item>Charles, Chaz</item>
+ <item>Charles, Buck</item>
<item>Christine, Chrissy, Chrissie</item>
<item>Christopher, Chris</item>
<item>Clinton, Clint</item>
- <item>Cynthia, Cindy, Cynth</item>
+ <item>Cynthia, Cindy</item>
+ <item>Cynthia, Cynth</item>
<item>Daniel, Dan, Danny</item>
<item>David, Dave</item>
<item>Deborah, Deb, Debbie</item>
@@ -43,30 +59,46 @@
<item>Dorothea, Dot, Dotty</item>
<item>Dorothy, Dot, Dotty</item>
<item>Douglas, Doug</item>
- <item>Edward, Ed, Eddie, Ned, Neddie, Neddy, Ted, Teddy, Teddie</item>
- <item>Eleanor, Ella, Ellie, Elle</item>
+ <item>Edward, Ed, Eddie</item>
+ <item>Edward, Ned, Neddie, Neddy</item>
+ <item>Edward, Ted, Teddy, Teddie</item>
+ <item>Eleanor, Ella</item>
+ <item>Eleanor, Ellie, Elle</item>
<item>Elisabetta, Betta</item>
- <item>Elizabeth, Beth, Bess, Bessie, Betsy, Betty, Bette, Eliza, Lisa, Liza, Liz</item>
+ <item>Elizabeth, Beth</item>
+ <item>Elizabeth, Bess, Bessie</item>
+ <item>Elizabeth, Betsy</item>
+ <item>Elizabeth, Betty, Bette</item>
+ <item>Elizabeth, Eliza</item>
+ <item>Elizabeth, Lisa, Liza, Liz</item>
<item>Emily, Em, Ems, Emmy</item>
<item>Emma, Em, Ems, Emmy</item>
<item>Eugene, Gene</item>
<item>Fannie, Fanny</item>
<item>Florence, Flo</item>
- <item>Frances, Fran, Francie</item>
- <item>Francis, Fran, Frank, Frankie</item>
+ <item>Frances, Fran</item>
+ <item>Frances, Francie</item>
+ <item>Francis, Fran</item>
+ <item>Francis, Frank, Frankie</item>
<item>Frederick, Fred, Freddy</item>
<item>Gabriel, Gabe</item>
<item>Gerald, Gerry</item>
<item>Gerard, Gerry</item>
<item>Gregory, Greg, Gregg</item>
- <item>Harold, Hal, Harry</item>
- <item>Henry, Hal, Hank, Harry</item>
+ <item>Harold, Hal</item>
+ <item>Harold, Harry</item>
+ <item>Henry, Hal</item>
+ <item>Henry, Hank</item>
+ <item>Henry, Harry</item>
<item>Herbert, Bert, Bertie</item>
<item>Irving, Irv</item>
- <item>Isabella, Isa, Izzy, Bella</item>
+ <item>Isabella, Isa</item>
+ <item>Isabella, Izzy</item>
+ <item>Isabella, Bella</item>
<item>Jacob, Jake</item>
<item>Jacqueline, Jackie</item>
- <item>James, Jim, Jimmy, Jamie, Jock</item>
+ <item>James, Jim, Jimmy</item>
+ <item>James, Jamie</item>
<item>Janet, Jan</item>
<item>Janice, Jan</item>
<item>Jason, Jay</item>
@@ -90,10 +122,15 @@
<item>Laura, Lauri, Laurie</item>
<item>Lauren, Lauri, Laurie</item>
<item>Lawrence, Larry</item>
- <item>Leonard, Leo, Len, Lenny</item>
- <item>Leopold, Leo, Len, Lenny</item>
+ <item>Leonard, Leo</item>
+ <item>Leonard, Len, Lenny</item>
+ <item>Leopold, Leo</item>
<item>Madeline, Maddie, Maddy</item>
- <item>Margaret, Marge, Marg, Maggie, Mags, Meg, Peggy, Greta, Gretchen</item>
+ <item>Margaret, Marge, Marg</item>
+ <item>Margaret, Maggie, Mags</item>
+ <item>Margaret, Meg</item>
+ <item>Margaret, Peggy</item>
+ <item>Margaret, Greta, Gretchen</item>
<item>Martin, Martie, Marty</item>
<item>Matthew, Matt, Mattie</item>
<item>Maureen, Mo</item>
@@ -101,27 +138,36 @@
<item>Maxwell, Max</item>
<item>Maximilian, Maxim, Max</item>
<item>Megan, Meg</item>
- <item>Michael, Mickey, Mick, Mike, Mikey</item>
+ <item>Michael, Mickey, Mick</item>
+ <item>Michael, Mike, Mikey</item>
<item>Morris, Mo</item>
<item>Nancy, Nan</item>
- <item>Nathan, Nat, Nate</item>
- <item>Nathaniel, Nat, Nate</item>
+ <item>Nathan, Nat</item>
+ <item>Nathan, Nate</item>
+ <item>Nathaniel, Nat</item>
+ <item>Nathaniel, Nate</item>
<item>Nicholas, Nick</item>
<item>Nicole, Nicky, Nickie, Nikky</item>
<item>Pamela, Pam</item>
- <item>Patricia, Pat, Patsy, Patty, Trish, Tricia</item>
- <item>Patrick, Pat, Patter</item>
+ <item>Patricia, Pat, Patty</item>
+ <item>Patricia, Patsy</item>
+ <item>Patricia, Trish, Tricia</item>
+ <item>Patrick, Pat</item>
<item>Penelope, Penny</item>
<item>Peter, Pete</item>
<item>Raymond, Ray</item>
<item>Philip, Phil</item>
<item>Rebecca, Becca, Becky</item>
- <item>Richard, Rick, Rich, Dick</item>
- <item>Robert, Bob, Rob, Robbie, Bobby, Rab</item>
+ <item>Richard, Rick</item>
+ <item>Richard, Rich</item>
+ <item>Richard, Dick</item>
+ <item>Robert, Bob, Bobby</item>
+ <item>Robert, Rob, Robbie</item>
<item>Rodney. Rod</item>
<item>Ronald, Ron, Ronnie</item>
<item>Rosemary, Rosie, Rose</item>
- <item>Russell, Russ, Rusty</item>
+ <item>Russell, Russ</item>
+ <item>Russell, Rusty</item>
<item>Ryan, Ry</item>
<item>Samantha, Sam</item>
<item>Samuel, Sam, Sammy</item>
@@ -130,23 +176,34 @@
<item>Stephen, Steve</item>
<item>Steven, Steve</item>
<item>Stuart, Stu</item>
- <item>Susan, Sue, Susie, Suzie</item>
- <item>Suzanne, Sue, Susie, Suzie</item>
+ <item>Susan, Sue</item>
+ <item>Susan, Susie, Suzie</item>
+ <item>Suzanne, Sue</item>
+ <item>Suzanne, Susie, Suzie</item>
<item>Tamara, Tammy</item>
<item>Theresa, Teresa</item>
- <item>Theodora, Teddie, Thea, Theo</item>
- <item>Theodore, Ted, Teddy, Theo</item>
+ <item>Theodora, Teddie</item>
+ <item>Theodora, Thea</item>
+ <item>Theodore, Ted, Teddy</item>
+ <item>Theodore, Theo</item>
<item>Thomas, Tom, Thom, Tommy</item>
<item>Timothy, Tim, Timmy</item>
<item>Valerie, Val</item>
- <item>Veronica, Ronnie, Roni, Nica, Nikki, Nikka</item>
+ <item>Veronica, Ronnie, Roni</item>
+ <item>Veronica, Nica, Nikki, Nikka</item>
<item>Victor, Vic</item>
- <item>Victoria, Vicky, Vicki, Vickie, Tori</item>
- <item>Vincent, Vince, Vin, Vinnie</item>
+ <item>Victoria, Vicky, Vicki, Vickie</item>
+ <item>Victoria, Tori</item>
+ <item>Vincent, Vince</item>
+ <item>Vincent, Vin, Vinnie</item>
<item>Vivian, Vivi</item>
- <item>Walter, Walt, Wally</item>
- <item>Wendy, Wen, Wendel</item>
- <item>William, Bill, Billy, Will, Willy, Liam</item>
+ <item>Walter, Wally</item>
+ <item>Walter, Walt</item>
+ <item>Wendy, Wen</item>
+ <item>Wendy, Wendel</item>
+ <item>William, Bill, Billy</item>
+ <item>William, Will, Willy</item>
+ <item>William, Liam</item>
<item>Yvonna, Vonna</item>
<item>Zachary, Zach, Zack, Zac</item>
</string-array>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index f00572d..4e2f9c3 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -531,8 +531,8 @@
<!-- The screen orientation has changed, that is the user has
rotated the device. -->
<flag name="orientation" value="0x0080" />
- <!-- The screen orientation has changed, that is the user has
- rotated the device. -->
+ <!-- The screen layout has changed. This might be caused by a
+ different display being activated. -->
<flag name="screenLayout" value="0x0100" />
<!-- The font scaling factor has changed, that is the user has
selected a new global font size. -->
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index cac26b9..8b6af71 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -67,4 +67,5 @@
<item type="id" name="addToDictionary" />
<item type="id" name="accountPreferences" />
<item type="id" name="smallIcon" />
+ <item type="id" name="custom" />
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 8c00884..a7336fc 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1238,6 +1238,8 @@
<public type="attr" name="overscrollHeader" id="0x010102bf" />
<public type="attr" name="overscrollFooter" id="0x010102c0" />
- <public type="anim" name="cycle_interpolator" id="0x010a000c" />
+ <public type="id" name="custom" id="0x0102002b" />
+ <public type="anim" name="cycle_interpolator" id="0x010a000c" />
+
</resources>
diff --git a/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
index c51fecc..89b3fb6 100644
--- a/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
+++ b/core/tests/coretests/src/android/os/HierarchicalStateMachineTest.java
@@ -48,7 +48,7 @@
private static final int TEST_CMD_6 = 6;
private static final boolean DBG = true;
- private static final boolean WAIT_FOR_DEBUGGER = false;
+ private static final boolean WAIT_FOR_DEBUGGER = true;
private static final String TAG = "HierarchicalStateMachineTest";
/**
@@ -152,6 +152,154 @@
}
/**
+ * Test enter/exit can use transitionTo
+ */
+ class StateMachineEnterExitTransitionToTest extends HierarchicalStateMachine {
+ StateMachineEnterExitTransitionToTest(String name) {
+ super(name);
+ mThisSm = this;
+ setDbg(DBG);
+
+ // Setup state machine with 1 state
+ addState(mS1);
+ addState(mS2);
+ addState(mS3);
+ addState(mS4);
+
+ // Set the initial state
+ setInitialState(mS1);
+ }
+
+ class S1 extends HierarchicalState {
+ @Override protected void enter() {
+ // Test that a transition in enter and the initial state works
+ mS1EnterCount += 1;
+ transitionTo(mS2);
+ Log.d(TAG, "S1.enter");
+ }
+ @Override protected void exit() {
+ mS1ExitCount += 1;
+ Log.d(TAG, "S1.exit");
+ }
+ }
+
+ class S2 extends HierarchicalState {
+ @Override protected void enter() {
+ mS2EnterCount += 1;
+ Log.d(TAG, "S2.enter");
+ }
+ @Override protected void exit() {
+ // Test transition in exit work
+ mS2ExitCount += 1;
+ transitionTo(mS4);
+ Log.d(TAG, "S2.exit");
+ }
+ @Override protected boolean processMessage(Message message) {
+ // Start a transition to S3 but it will be
+ // changed to a transition to S4
+ transitionTo(mS3);
+ Log.d(TAG, "S2.processMessage");
+ return true;
+ }
+ }
+
+ class S3 extends HierarchicalState {
+ @Override protected void enter() {
+ // Test that we can do halting in an enter/exit
+ transitionToHaltingState();
+ mS3EnterCount += 1;
+ Log.d(TAG, "S3.enter");
+ }
+ @Override protected void exit() {
+ mS3ExitCount += 1;
+ Log.d(TAG, "S3.exit");
+ }
+ }
+
+
+ class S4 extends HierarchicalState {
+ @Override protected void enter() {
+ // Test that we can do halting in an enter/exit
+ transitionToHaltingState();
+ mS4EnterCount += 1;
+ Log.d(TAG, "S4.enter");
+ }
+ @Override protected void exit() {
+ mS4ExitCount += 1;
+ Log.d(TAG, "S4.exit");
+ }
+ }
+
+ @Override
+ protected void halting() {
+ synchronized (mThisSm) {
+ mThisSm.notifyAll();
+ }
+ }
+
+ private StateMachineEnterExitTransitionToTest mThisSm;
+ private S1 mS1 = new S1();
+ private S2 mS2 = new S2();
+ private S3 mS3 = new S3();
+ private S4 mS4 = new S4();
+ private int mS1EnterCount = 0;
+ private int mS1ExitCount = 0;
+ private int mS2EnterCount = 0;
+ private int mS2ExitCount = 0;
+ private int mS3EnterCount = 0;
+ private int mS3ExitCount = 0;
+ private int mS4EnterCount = 0;
+ private int mS4ExitCount = 0;
+ }
+
+ @SmallTest
+ public void testStateMachineEnterExitTransitionToTest() throws Exception {
+ //if (WAIT_FOR_DEBUGGER) Debug.waitForDebugger();
+
+ StateMachineEnterExitTransitionToTest smEnterExitTranstionToTest =
+ new StateMachineEnterExitTransitionToTest("smEnterExitTranstionToTest");
+ smEnterExitTranstionToTest.start();
+ if (smEnterExitTranstionToTest.isDbg()) {
+ Log.d(TAG, "testStateMachineEnterExitTransitionToTest E");
+ }
+
+ synchronized (smEnterExitTranstionToTest) {
+ smEnterExitTranstionToTest.sendMessage(1);
+
+ try {
+ // wait for the messages to be handled
+ smEnterExitTranstionToTest.wait();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "testStateMachineEnterExitTransitionToTest: exception while waiting "
+ + e.getMessage());
+ }
+ }
+
+ assertTrue(smEnterExitTranstionToTest.getProcessedMessagesCount() == 1);
+
+ ProcessedMessages.Info pmi;
+
+ // Message should be handled by mS2.
+ pmi = smEnterExitTranstionToTest.getProcessedMessage(0);
+ assertEquals(TEST_CMD_1, pmi.getWhat());
+ assertEquals(smEnterExitTranstionToTest.mS2, pmi.getState());
+ assertEquals(smEnterExitTranstionToTest.mS2, pmi.getOriginalState());
+
+ assertEquals(smEnterExitTranstionToTest.mS1EnterCount, 1);
+ assertEquals(smEnterExitTranstionToTest.mS1ExitCount, 1);
+ assertEquals(smEnterExitTranstionToTest.mS2EnterCount, 1);
+ assertEquals(smEnterExitTranstionToTest.mS2ExitCount, 1);
+ assertEquals(smEnterExitTranstionToTest.mS3EnterCount, 1);
+ assertEquals(smEnterExitTranstionToTest.mS3ExitCount, 1);
+ assertEquals(smEnterExitTranstionToTest.mS3EnterCount, 1);
+ assertEquals(smEnterExitTranstionToTest.mS3ExitCount, 1);
+
+ if (smEnterExitTranstionToTest.isDbg()) {
+ Log.d(TAG, "testStateMachineEnterExitTransitionToTest X");
+ }
+ }
+
+ /**
* Tests that ProcessedMessage works as a circular buffer.
*/
class StateMachine0 extends HierarchicalStateMachine {
diff --git a/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java b/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java
index 019b9e3..c3f6f79 100644
--- a/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java
+++ b/core/tests/coretests/src/android/pim/vcard/ImportTestResolver.java
@@ -215,7 +215,7 @@
mTestCase.fail("Unexpected Uri has come: " + uri);
}
} // for (int i = 0; i < size; i++) {
- return null;
+ return fakeResultArray;
}
public void verify() {
diff --git a/include/tts/TtsEngine.h b/include/tts/TtsEngine.h
index 28b0d2f..998e353 100644
--- a/include/tts/TtsEngine.h
+++ b/include/tts/TtsEngine.h
@@ -26,6 +26,12 @@
namespace android {
+#define ANDROID_TTS_ENGINE_PROPERTY_CONFIG "engineConfig"
+#define ANDROID_TTS_ENGINE_PROPERTY_PITCH "pitch"
+#define ANDROID_TTS_ENGINE_PROPERTY_RATE "rate"
+#define ANDROID_TTS_ENGINE_PROPERTY_VOLUME "volume"
+
+
enum tts_synth_status {
TTS_SYNTH_DONE = 0,
TTS_SYNTH_PENDING = 1
@@ -85,7 +91,7 @@
// Initialize the TTS engine and returns whether initialization succeeded.
// @param synthDoneCBPtr synthesis callback function pointer
// @return TTS_SUCCESS, or TTS_FAILURE
- virtual tts_result init(synthDoneCB_t synthDoneCBPtr);
+ virtual tts_result init(synthDoneCB_t synthDoneCBPtr, const char *engineConfig);
// Shut down the TTS engine and releases all associated resources.
// @return TTS_SUCCESS, or TTS_FAILURE
@@ -122,7 +128,7 @@
// @param variant pointer to the variant code
// @return TTS_SUCCESS, or TTS_FAILURE
virtual tts_result loadLanguage(const char *lang, const char *country, const char *variant);
-
+
// Load the resources associated with the specified language, country and Locale variant.
// The loaded language will only be used once a call to setLanguageFromLocale() with the same
// language value is issued. Language and country values are coded according to the ISO three
@@ -220,19 +226,6 @@
virtual tts_result synthesizeText(const char *text, int8_t *buffer,
size_t bufferSize, void *userdata);
- // Synthesize IPA text.
- // As the synthesis is performed, the engine invokes the callback to notify
- // the TTS framework that it has filled the given buffer, and indicates how
- // many bytes it wrote. The callback is called repeatedly until the engine
- // has generated all the audio data corresponding to the IPA data.
- // @param ipa the IPA data to synthesize
- // @param userdata pointer to be returned when the call is invoked
- // @param buffer the location where the synthesized data must be written
- // @param bufferSize the number of bytes that can be written in buffer
- // @return TTS_FEATURE_UNSUPPORTED if IPA is not supported,
- // otherwise TTS_SUCCESS or TTS_FAILURE
- virtual tts_result synthesizeIpa(const char *ipa, int8_t *buffer,
- size_t bufferSize, void *userdata);
};
} // namespace android
diff --git a/libs/rs/java/Fountain/res/raw/fountain2.rs b/libs/rs/java/Fountain/res/raw/fountain2.rs
new file mode 100644
index 0000000..3301140
--- /dev/null
+++ b/libs/rs/java/Fountain/res/raw/fountain2.rs
@@ -0,0 +1,73 @@
+// Fountain test script
+#pragma version(1)
+
+#include "rs_types.rsh"
+#include "rs_math.rsh"
+#include "rs_graphics.rsh"
+
+static int newPart = 0;
+
+typedef struct Control_s {
+ int x, y;
+ int rate;
+ int count;
+ float r, g, b;
+ rs_allocation partBuffer;
+ rs_mesh partMesh;
+} Control_t;
+Control_t *Control;
+
+typedef struct Point_s{
+ float2 delta;
+ float2 position;
+ unsigned int color;
+} Point_t;
+Point_t *point;
+
+int main(int launchID) {
+ int ct;
+ int count = Control->count;
+ int rate = Control->rate;
+ float height = getHeight();
+ Point_t * p = point;
+
+ if (rate) {
+ float rMax = ((float)rate) * 0.005f;
+ int x = Control->x;
+ int y = Control->y;
+ int color = ((int)(Control->r * 255.f)) |
+ ((int)(Control->g * 255.f)) << 8 |
+ ((int)(Control->b * 255.f)) << 16 |
+ (0xf0 << 24);
+ Point_t * np = &p[newPart];
+
+ while (rate--) {
+ np->delta = vec2Rand(rMax);
+ np->position.x = x;
+ np->position.y = y;
+ np->color = color;
+ newPart++;
+ np++;
+ if (newPart >= count) {
+ newPart = 0;
+ np = &p[newPart];
+ }
+ }
+ }
+
+ for (ct=0; ct < count; ct++) {
+ float dy = p->delta.y + 0.15f;
+ float posy = p->position.y + dy;
+ if ((posy > height) && (dy > 0)) {
+ dy *= -0.3f;
+ }
+ p->delta.y = dy;
+ p->position.x += p->delta.x;
+ p->position.y = posy;
+ p++;
+ }
+
+ uploadToBufferObject(Control->partBuffer);
+ drawSimpleMesh(Control->partMesh);
+ return 1;
+}
diff --git a/libs/rs/scriptc/rs_graphics.rsh b/libs/rs/scriptc/rs_graphics.rsh
new file mode 100644
index 0000000..70cd562
--- /dev/null
+++ b/libs/rs/scriptc/rs_graphics.rsh
@@ -0,0 +1,65 @@
+
+
+extern float2 vec2Rand(float len);
+
+extern float3 float3Norm(float3);
+extern float float3Length(float3);
+extern float3 float3Add(float3 lhs, float3 rhs);
+extern float3 float3Sub(float3 lhs, float3 rhs);
+extern float3 float3Cross(float3 lhs, float3 rhs);
+extern float float3Dot(float3 lhs, float3 rhs);
+extern float3 float3Scale(float3 v, float scale);
+
+extern float4 float4Add(float4 lhs, float4 rhs);
+extern float4 float4Sub(float4 lhs, float4 rhs);
+extern float4 float4Cross(float4 lhs, float4 rhs);
+extern float float4Dot(float4 lhs, float4 rhs);
+extern float4 float4Scale(float4 v, float scale);
+
+ // context
+extern void bindProgramFragment(rs_program_fragment);
+extern void bindProgramStore(rs_program_store);
+extern void bindProgramVertex(rs_program_vertex);
+
+extern void bindSampler(rs_program_fragment, int slot, rs_sampler);
+extern void bindSampler(rs_program_fragment, int slot, rs_allocation);
+
+extern void vpLoadModelMatrix(const float *);
+extern void vpLoadTextureMatrix(const float *);
+
+
+// drawing
+extern void drawRect(float x1, float y1, float x2, float y2, float z);
+extern void drawQuad(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4);
+extern void drawQuadTexCoords(float x1, float y1, float z1, float u1, float v1, float x2, float y2, float z2, float u2, float v2, float x3, float y3, float z3, float u3, float v3, float x4, float y4, float z4, float u4, float v4);
+extern void drawSprite(float x, float y, float z, float w, float h);
+extern void drawSpriteScreenspace(float x, float y, float z, float w, float h);
+extern void drawLine(float x1, float y1, float z1, float x2, float y2, float z2);
+extern void drawPoint(float x1, float y1, float z1);
+extern void drawSimpleMesh(int ism);
+extern void drawSimpleMeshRange(int ism, int start, int len);
+
+// misc
+extern void pfClearColor(float, float, float, float);
+extern void color(float, float, float, float);
+extern void hsb(float, float, float, float);
+extern void hsbToRgb(float, float, float, float*);
+extern int hsbToAbgr(float, float, float, float);
+
+extern void uploadToTexture(int, int);
+extern void uploadToBufferObject(int);
+
+extern int colorFloatRGBAtoUNorm8(float, float, float, float);
+extern int colorFloatRGBto565(float, float, float);
+
+extern int getWidth();
+extern int getHeight();
+
+extern int sendToClient(void *data, int cmdID, int len, int waitForSpace);
+
+extern void debugF(const char *, float);
+extern void debugI32(const char *, int);
+extern void debugHexI32(const char *, int);
+
+
+
diff --git a/libs/rs/scriptc/rs_types.rsh b/libs/rs/scriptc/rs_types.rsh
index ae1acdb..4198a74 100644
--- a/libs/rs/scriptc/rs_types.rsh
+++ b/libs/rs/scriptc/rs_types.rsh
@@ -14,16 +14,16 @@
typedef uint32_t uint;
//typedef uint64_t ulong;
-typedef void * rs_element;
-typedef void * rs_type;
-typedef void * rs_allocation;
-typedef void * rs_sampler;
-typedef void * rs_script;
-typedef void * rs_mesh;
-typedef void * rs_program_fragment;
-typedef void * rs_program_vertex;
-typedef void * rs_program_raster;
-typedef void * rs_program_store;
+typedef int rs_element;
+typedef int rs_type;
+typedef int rs_allocation;
+typedef int rs_sampler;
+typedef int rs_script;
+typedef int rs_mesh;
+typedef int rs_program_fragment;
+typedef int rs_program_vertex;
+typedef int rs_program_raster;
+typedef int rs_program_store;
typedef float float2 __attribute__((ext_vector_type(2)));
typedef float float3 __attribute__((ext_vector_type(3)));
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 3a3c66b..104ecb4 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -693,10 +693,8 @@
//====================================================================
// Bluetooth SCO control
/**
- * @hide
- * TODO unhide for SDK
* Sticky broadcast intent action indicating that the bluetoooth SCO audio
- * connection state has changed. The intent contains on extra {@link EXTRA_SCO_AUDIO_STATE}
+ * connection state has changed. The intent contains on extra {@link #EXTRA_SCO_AUDIO_STATE}
* indicating the new state which is either {@link #SCO_AUDIO_STATE_DISCONNECTED}
* or {@link #SCO_AUDIO_STATE_CONNECTED}
*
@@ -706,8 +704,6 @@
public static final String ACTION_SCO_AUDIO_STATE_CHANGED =
"android.media.SCO_AUDIO_STATE_CHANGED";
/**
- * @hide
- * TODO unhide for SDK
* Extra for intent {@link #ACTION_SCO_AUDIO_STATE_CHANGED} containing the new
* bluetooth SCO connection state.
*/
@@ -715,22 +711,16 @@
"android.media.extra.SCO_AUDIO_STATE";
/**
- * @hide
- * TODO unhide for SDK
* Value for extra {@link #EXTRA_SCO_AUDIO_STATE} indicating that the
* SCO audio channel is not established
*/
public static final int SCO_AUDIO_STATE_DISCONNECTED = 0;
/**
- * @hide
- * TODO unhide for SDK
* Value for extra {@link #EXTRA_SCO_AUDIO_STATE} indicating that the
* SCO audio channel is established
*/
public static final int SCO_AUDIO_STATE_CONNECTED = 1;
/**
- * @hide
- * TODO unhide for SDK
* Value for extra {@link #EXTRA_SCO_AUDIO_STATE} indicating that
* there was an error trying to obtain the state
*/
@@ -738,8 +728,6 @@
/**
- * @hide
- * TODO unhide for SDK
* Indicates if current platform supports use of SCO for off call use cases.
* Application wanted to use bluetooth SCO audio when the phone is not in call
* must first call thsi method to make sure that the platform supports this
@@ -754,8 +742,6 @@
}
/**
- * @hide
- * TODO unhide for SDK
* Start bluetooth SCO audio connection.
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
@@ -772,7 +758,7 @@
* down the bluetooth connection.
* <p>Even if a SCO connection is established, the following restrictions apply on audio
* output streams so that they can be routed to SCO headset:
- * - the stream type must be {@link #STREAM_VOICE_CALL} or {@link #STREAM_BLUETOOTH_SCO}
+ * - the stream type must be {@link #STREAM_VOICE_CALL}
* - the format must be mono
* - the sampling must be 16kHz or 8kHz
* <p>The following restrictions apply on input streams:
@@ -797,8 +783,6 @@
}
/**
- * @hide
- * TODO unhide for SDK
* Stop bluetooth SCO audio connection.
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_AUDIO_SETTINGS}.
@@ -1260,16 +1244,6 @@
}
/**
- * Used to indicate a loss of audio focus of unknown duration.
- * @see OnAudioFocusChangeListener#onAudioFocusChanged(int)
- */
- public static final int AUDIOFOCUS_LOSS = -1;
- /**
- * Used to indicate a transient loss of audio focus.
- * @see OnAudioFocusChangeListener#onAudioFocusChanged(int)
- */
- public static final int AUDIOFOCUS_LOSS_TRANSIENT = -2;
- /**
* Used to indicate a gain of audio focus, or a request of audio focus, of unknown duration.
* @see OnAudioFocusChangeListener#onAudioFocusChanged(int)
* @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
@@ -1283,6 +1257,35 @@
* @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
*/
public static final int AUDIOFOCUS_GAIN_TRANSIENT = 2;
+ /**
+ * @hide
+ * Used to indicate a temporary request of audio focus, anticipated to last a short
+ * amount of time, and where it is acceptable for other audio applications to duck.
+ * Examples of temporary changes are the playback of driving directions where playback of music
+ * in the background is acceptable.
+ * @see OnAudioFocusChangeListener#onAudioFocusChanged(int)
+ * @see #requestAudioFocus(OnAudioFocusChangeListener, int, int)
+ */
+ public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK = 3;
+ /**
+ * Used to indicate a loss of audio focus of unknown duration.
+ * @see OnAudioFocusChangeListener#onAudioFocusChanged(int)
+ */
+ public static final int AUDIOFOCUS_LOSS = -1 * AUDIOFOCUS_GAIN;
+ /**
+ * Used to indicate a transient loss of audio focus.
+ * @see OnAudioFocusChangeListener#onAudioFocusChanged(int)
+ */
+ public static final int AUDIOFOCUS_LOSS_TRANSIENT = -1 * AUDIOFOCUS_GAIN_TRANSIENT;
+ /**
+ * @hide
+ * Used to indicate a transient loss of audio focus where the loser of the audio focus can
+ * duck if it wants to continue playing, as the new focus owner doesn't require others
+ * to be silent.
+ * @see OnAudioFocusChangeListener#onAudioFocusChanged(int)
+ */
+ public static final int AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK =
+ -1 * AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK;
/**
* Interface definition for a callback to be invoked when the audio focus of the system is
@@ -1298,7 +1301,7 @@
* behavior to adopt when losing focus. A music player could for instance elect to duck its
* music stream for transient focus losses, and pause otherwise.
* @param focusChange one of {@link AudioManager#AUDIOFOCUS_GAIN},
- * {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}.
+ * {@link AudioManager#AUDIOFOCUS_LOSS}, {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT}
*/
public void onAudioFocusChanged(int focusChange);
}
@@ -1324,14 +1327,7 @@
*/
private FocusEventHandlerDelegate mAudioFocusEventHandlerDelegate =
new FocusEventHandlerDelegate();
- /**
- * Event id denotes a loss of focus
- */
- private static final int AUDIOFOCUS_EVENT_LOSS = 0;
- /**
- * Event id denotes a gain of focus
- */
- private static final int AUDIOFOCUS_EVENT_GAIN = 1;
+
/**
* Helper class to handle the forwarding of audio focus events to the appropriate listener
*/
@@ -1432,8 +1428,8 @@
* @param streamType the main audio stream type affected by the focus request
* @param durationHint use {@link #AUDIOFOCUS_GAIN_TRANSIENT} to indicate this focus request
* is temporary, and focus will be abandonned shortly. Examples of transient requests are
- * for the playback of driving directions, or notifications sounds. Use
- * {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
+ * for the playback of driving directions, or notifications sounds.
+ * Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
* as the playback of a song or a video.
* @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
*/
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 75e51f9..1992c93 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1822,7 +1822,7 @@
public IAudioFocusDispatcher mFocusDispatcher = null;
public IBinder mSourceRef = null;
public String mClientId;
- public int mDurationHint;
+ public int mFocusChangeType;
public FocusStackEntry() {
}
@@ -1834,7 +1834,7 @@
mFocusDispatcher = afl;
mSourceRef = source;
mClientId = id;
- mDurationHint = duration;
+ mFocusChangeType = duration;
}
}
@@ -1851,7 +1851,7 @@
while(stackIterator.hasNext()) {
FocusStackEntry fse = stackIterator.next();
pw.println(" source:" + fse.mSourceRef + " -- client: " + fse.mClientId
- + " -- duration: " +fse.mDurationHint);
+ + " -- duration: " +fse.mFocusChangeType);
}
}
}
@@ -1953,7 +1953,7 @@
/** @see AudioManager#requestAudioFocus(IAudioFocusDispatcher, int, int) */
- public int requestAudioFocus(int mainStreamType, int durationHint, IBinder cb,
+ public int requestAudioFocus(int mainStreamType, int focusChangeHint, IBinder cb,
IAudioFocusDispatcher fd, String clientId) {
Log.i(TAG, " AudioFocus requestAudioFocus() from " + clientId);
// the main stream type for the audio focus request is currently not used. It may
@@ -1970,7 +1970,7 @@
synchronized(mFocusStack) {
if (!mFocusStack.empty() && mFocusStack.peek().mClientId.equals(clientId)) {
- mFocusStack.peek().mDurationHint = durationHint;
+ mFocusStack.peek().mFocusChangeType = focusChangeHint;
// if focus is already owned by this client, don't do anything
return AudioManager.AUDIOFOCUS_REQUEST_GRANTED;
}
@@ -1979,9 +1979,7 @@
if (!mFocusStack.empty() && (mFocusStack.peek().mFocusDispatcher != null)) {
try {
mFocusStack.peek().mFocusDispatcher.dispatchAudioFocusChange(
- (durationHint == AudioManager.AUDIOFOCUS_GAIN) ?
- AudioManager.AUDIOFOCUS_LOSS :
- AudioManager.AUDIOFOCUS_LOSS_TRANSIENT,
+ -1 * focusChangeHint, // loss and gain codes are inverse of each other
mFocusStack.peek().mClientId);
} catch (RemoteException e) {
Log.e(TAG, " Failure to signal loss of focus due to "+ e);
@@ -1990,7 +1988,7 @@
}
// push focus requester at the top of the audio focus stack
- mFocusStack.push(new FocusStackEntry(mainStreamType, durationHint, false, fd, cb,
+ mFocusStack.push(new FocusStackEntry(mainStreamType, focusChangeHint, false, fd, cb,
clientId));
}//synchronized(mFocusStack)
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 1047fa4..e9bcafe 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -634,7 +634,11 @@
} else if (MediaFile.isImageFileType(mFileType)) {
// FIXME - add DESCRIPTION
} else if (MediaFile.isAudioFileType(mFileType)) {
- map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0 ? mArtist : MediaStore.UNKNOWN_STRING));
+ String artist = mArtist != null && mArtist.length() > 0 ?
+ mArtist : MediaStore.UNKNOWN_STRING;
+ map.put(Audio.Media.ARTIST, artist);
+ map.put(Audio.Media.ALBUM_ARTIST, mAlbumArtist != null &&
+ mAlbumArtist.length() > 0 ? mAlbumArtist : artist);
map.put(Audio.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0 ? mAlbum : MediaStore.UNKNOWN_STRING));
map.put(Audio.Media.COMPOSER, mComposer);
if (mYear != 0) {
diff --git a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
index fbb6598..553be87 100644
--- a/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
+++ b/media/libstagefright/codecs/amrnb/dec/AMRNBDecoder.cpp
@@ -21,6 +21,7 @@
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
+#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
namespace android {
@@ -161,7 +162,14 @@
buffer->set_range(0, kNumSamplesPerFrame * sizeof(int16_t));
- CHECK(numBytesRead <= mInputBuffer->range_length());
+ if (numBytesRead > mInputBuffer->range_length()) {
+ // This is bad, should never have happened, but did. Abort now.
+
+ buffer->release();
+ buffer = NULL;
+
+ return ERROR_MALFORMED;
+ }
mInputBuffer->set_range(
mInputBuffer->range_offset() + numBytesRead,
diff --git a/media/libstagefright/omx/tests/OMXHarness.cpp b/media/libstagefright/omx/tests/OMXHarness.cpp
index c05d90a..fcf506d 100644
--- a/media/libstagefright/omx/tests/OMXHarness.cpp
+++ b/media/libstagefright/omx/tests/OMXHarness.cpp
@@ -595,6 +595,9 @@
static const int32_t kNumIterations = 5000;
+ // We are always going to seek beyond EOS in the first iteration (i == 0)
+ // followed by a linear read for the second iteration (i == 1).
+ // After that it's all random.
for (int32_t i = 0; i < kNumIterations; ++i) {
int64_t requestedSeekTimeUs;
int64_t actualSeekTimeUs;
@@ -602,14 +605,14 @@
double r = uniform_rand();
- if (i > 0 && r < 0.5) {
+ if ((i == 1) || (i > 0 && r < 0.5)) {
// 50% chance of just continuing to decode from last position.
requestedSeekTimeUs = -1;
LOGI("requesting linear read");
} else {
- if (i > 0 && r < 0.55) {
+ if (i == 0 || r < 0.55) {
// 5% chance of seeking beyond end of stream.
requestedSeekTimeUs = durationUs;
@@ -674,7 +677,15 @@
buffer = NULL;
}
} else if (actualSeekTimeUs < 0) {
- CHECK(err != OK);
+ EXPECT(err != OK,
+ "We attempted to seek beyond EOS and expected "
+ "ERROR_END_OF_STREAM to be returned, but instead "
+ "we got a valid buffer.");
+ EXPECT(err == ERROR_END_OF_STREAM,
+ "We attempted to seek beyond EOS and expected "
+ "ERROR_END_OF_STREAM to be returned, but instead "
+ "we found some other error.");
+ CHECK_EQ(err, ERROR_END_OF_STREAM);
CHECK_EQ(buffer, NULL);
} else {
EXPECT(err == OK,
diff --git a/packages/TtsService/jni/android_tts_SynthProxy.cpp b/packages/TtsService/jni/android_tts_SynthProxy.cpp
index b7acd96..1d69361 100644
--- a/packages/TtsService/jni/android_tts_SynthProxy.cpp
+++ b/packages/TtsService/jni/android_tts_SynthProxy.cpp
@@ -383,7 +383,7 @@
// ----------------------------------------------------------------------------
static int
android_tts_SynthProxy_native_setup(JNIEnv *env, jobject thiz,
- jobject weak_this, jstring nativeSoLib)
+ jobject weak_this, jstring nativeSoLib, jstring engConfig)
{
int result = TTS_FAILURE;
@@ -395,6 +395,7 @@
DEFAULT_TTS_STREAM_TYPE, DEFAULT_TTS_RATE, DEFAULT_TTS_FORMAT, DEFAULT_TTS_NB_CHANNELS);
const char *nativeSoLibNativeString = env->GetStringUTFChars(nativeSoLib, 0);
+ const char *engConfigString = env->GetStringUTFChars(engConfig, 0);
void *engine_lib_handle = dlopen(nativeSoLibNativeString,
RTLD_NOW | RTLD_LOCAL);
@@ -409,7 +410,7 @@
if (pJniStorage->mNativeSynthInterface) {
Mutex::Autolock l(engineMutex);
- pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB);
+ pJniStorage->mNativeSynthInterface->init(ttsSynthDoneCB, engConfigString);
}
result = TTS_SUCCESS;
@@ -422,6 +423,7 @@
env->SetIntField(thiz, javaTTSFields.synthProxyFieldJniData, (int)pJniStorage);
env->ReleaseStringUTFChars(nativeSoLib, nativeSoLibNativeString);
+ env->ReleaseStringUTFChars(engConfig, engConfigString);
return result;
}
@@ -482,6 +484,29 @@
return result;
}
+static int
+android_tts_SynthProxy_setConfig(JNIEnv *env, jobject thiz, jint jniData, jstring engineConfig)
+{
+ int result = TTS_FAILURE;
+
+ if (jniData == 0) {
+ LOGE("android_tts_SynthProxy_setConfig(): invalid JNI data");
+ return result;
+ }
+
+ Mutex::Autolock l(engineMutex);
+
+ SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
+ const char *engineConfigNativeString = env->GetStringUTFChars(engineConfig, 0);
+
+ if (pSynthData->mNativeSynthInterface) {
+ result = pSynthData->mNativeSynthInterface->setProperty(ANDROID_TTS_ENGINE_PROPERTY_CONFIG,
+ engineConfigNativeString, strlen(engineConfigNativeString));
+ }
+ env->ReleaseStringUTFChars(engineConfig, engineConfigNativeString);
+
+ return result;
+}
static int
android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
@@ -867,6 +892,10 @@
"(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
(void*)android_tts_SynthProxy_isLanguageAvailable
},
+ { "native_setConfig",
+ "(ILjava/lang/String;)I",
+ (void*)android_tts_SynthProxy_setConfig
+ },
{ "native_setLanguage",
"(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
(void*)android_tts_SynthProxy_setLanguage
@@ -896,7 +925,7 @@
(void*)android_tts_SynthProxy_shutdown
},
{ "native_setup",
- "(Ljava/lang/Object;Ljava/lang/String;)I",
+ "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;)I",
(void*)android_tts_SynthProxy_native_setup
},
{ "native_setLowShelf",
diff --git a/packages/TtsService/src/android/tts/SynthProxy.java b/packages/TtsService/src/android/tts/SynthProxy.java
index 5f283e1..525a504 100755
--- a/packages/TtsService/src/android/tts/SynthProxy.java
+++ b/packages/TtsService/src/android/tts/SynthProxy.java
@@ -51,7 +51,7 @@
public SynthProxy(String nativeSoLib, String engineConfig) {
boolean applyFilter = nativeSoLib.toLowerCase().contains("pico");
Log.v(TtsService.SERVICE_TAG, "About to load "+ nativeSoLib + ", applyFilter="+applyFilter);
- native_setup(new WeakReference<SynthProxy>(this), nativeSoLib);
+ native_setup(new WeakReference<SynthProxy>(this), nativeSoLib, engineConfig);
native_setLowShelf(applyFilter, PICO_FILTER_GAIN, PICO_FILTER_LOWSHELF_ATTENUATION,
PICO_FILTER_TRANSITION_FREQ, PICO_FILTER_SHELF_SLOPE);
}
@@ -105,10 +105,10 @@
}
/**
- * Sets the engine configuration.
+ * Updates the engine configuration.
*/
public int setConfig(String engineConfig) {
- return android.speech.tts.TextToSpeech.SUCCESS;
+ return native_setConfig(mJniData, engineConfig);
}
/**
@@ -180,7 +180,8 @@
*/
private int mJniData = 0;
- private native final int native_setup(Object weak_this, String nativeSoLib);
+ private native final int native_setup(Object weak_this, String nativeSoLib,
+ String engineConfig);
private native final int native_setLowShelf(boolean applyFilter, float filterGain,
float attenuationInDb, float freqInHz, float slope);
@@ -204,6 +205,8 @@
private native final int native_loadLanguage(int jniData, String language, String country,
String variant);
+ private native final int native_setConfig(int jniData, String engineConfig);
+
private native final int native_setSpeechRate(int jniData, int speechRate);
private native final int native_setPitch(int jniData, int speechRate);
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index b114ca2..5be919d 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -460,17 +460,17 @@
throw new IllegalStateException("Got an empty response");
}
- public void startAccessPoint(WifiConfiguration wifiConfig, String intf)
+ public void startAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
throws IllegalStateException {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
- mConnector.doCommand(String.format("softap stop " + intf));
- mConnector.doCommand(String.format("softap fwreload " + intf + " AP"));
- mConnector.doCommand(String.format("softap start " + intf));
+ android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
+ mConnector.doCommand(String.format("softap stop " + wlanIface));
+ mConnector.doCommand(String.format("softap fwreload " + wlanIface + " AP"));
+ mConnector.doCommand(String.format("softap start " + wlanIface));
if (wifiConfig == null) {
- mConnector.doCommand(String.format("softap set " + intf + " wl0.1"));
+ mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
} else {
/**
* softap set arg1 arg2 arg3 [arg4 arg5 arg6 arg7 arg8]
@@ -482,10 +482,9 @@
* argv6 - Channel
* argv7 - Preamble
* argv8 - Max SCB
- *
- * TODO: get a configurable softap interface from driver
*/
- String str = String.format("softap set " + intf + " wl0.1 %s %s %s", wifiConfig.SSID,
+ String str = String.format("softap set " + wlanIface + " " + softapIface + " %s %s %s",
+ wifiConfig.SSID,
wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
"wpa2-psk" : "open",
wifiConfig.preSharedKey);
@@ -498,8 +497,25 @@
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
+ android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
mConnector.doCommand("softap stopap");
}
+ public void setAccessPoint(WifiConfiguration wifiConfig, String wlanIface, String softapIface)
+ throws IllegalStateException {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.CHANGE_WIFI_STATE, "NetworkManagementService");
+ if (wifiConfig == null) {
+ mConnector.doCommand(String.format("softap set " + wlanIface + " " + softapIface));
+ } else {
+ String str = String.format("softap set " + wlanIface + " " + softapIface +
+ " %s %s %s", wifiConfig.SSID,
+ wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA_PSK) ?
+ "wpa2-psk" : "open",
+ wifiConfig.preSharedKey);
+ mConnector.doCommand(str);
+ }
+ }
}
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 87a744e..05558d4 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -851,7 +851,8 @@
mFrameworkInstallObserver = new AppDirObserver(
mFrameworkDir.getPath(), OBSERVER_EVENTS, true);
mFrameworkInstallObserver.startWatching();
- scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM,
+ scanDirLI(mFrameworkDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR,
scanMode | SCAN_NO_DEX);
// Collect all system packages.
@@ -859,7 +860,8 @@
mSystemInstallObserver = new AppDirObserver(
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
mSystemInstallObserver.startWatching();
- scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM, scanMode);
+ scanDirLI(mSystemAppDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR, scanMode);
if (mInstaller != null) {
if (DEBUG_UPGRADE) Log.v(TAG, "Running installd update commands");
@@ -2711,8 +2713,6 @@
SharedUserSetting suid = null;
PackageSetting pkgSetting = null;
- boolean removeExisting = false;
-
if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
// Only system apps can use these features.
pkg.mOriginalPackages = null;
@@ -2903,7 +2903,7 @@
if (!verifySignaturesLP(pkgSetting, pkg, parseFlags,
(scanMode&SCAN_UPDATE_SIGNATURE) != 0)) {
- if ((parseFlags&PackageParser.PARSE_IS_SYSTEM) == 0) {
+ if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
return null;
}
@@ -2922,7 +2922,10 @@
return null;
}
}
- removeExisting = true;
+ // File a report about this.
+ String msg = "System package " + pkg.packageName
+ + " signature changed; retaining data.";
+ reportSettingsProblem(Log.WARN, msg);
}
// Verify that this new package doesn't have any content providers
@@ -2955,23 +2958,6 @@
final String pkgName = pkg.packageName;
- if (removeExisting) {
- boolean useEncryptedFSDir = useEncryptedFilesystemForPackage(pkg);
- if (mInstaller != null) {
- int ret = mInstaller.remove(pkgName, useEncryptedFSDir);
- if (ret != 0) {
- String msg = "System package " + pkg.packageName
- + " could not have data directory erased after signature change.";
- reportSettingsProblem(Log.WARN, msg);
- mLastScanError = PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE;
- return null;
- }
- }
- Slog.w(TAG, "System package " + pkg.packageName
- + " signature changed: existing data removed.");
- mLastScanError = PackageManager.INSTALL_SUCCEEDED;
- }
-
if (pkg.mAdoptPermissions != null) {
// This package wants to adopt ownership of permissions from
// another package.
@@ -4500,7 +4486,8 @@
if ((event&ADD_EVENTS) != 0) {
if (p == null) {
p = scanPackageLI(fullPath,
- (mIsRom ? PackageParser.PARSE_IS_SYSTEM : 0) |
+ (mIsRom ? PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR: 0) |
PackageParser.PARSE_CHATTY |
PackageParser.PARSE_MUST_BE_APK,
SCAN_MONITOR | SCAN_NO_PATHS);
@@ -4701,23 +4688,22 @@
}
return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
} else {
- // When replacing apps make sure we honour
- // the existing app location if not overwritten by other options
- boolean prevOnSd = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
if (onSd) {
// Install flag overrides everything.
return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
}
- // If current upgrade does not specify install location.
+ // If current upgrade specifies particular preference
if (installLocation == PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY) {
// Application explicitly specified internal.
return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
} else if (installLocation == PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL) {
// App explictly prefers external. Let policy decide
- } else if (installLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
+ } else {
// Prefer previous location
- return prevOnSd ? PackageHelper.RECOMMEND_INSTALL_EXTERNAL:
- PackageHelper.RECOMMEND_INSTALL_INTERNAL;
+ if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
+ return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
+ }
+ return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
}
}
} else {
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 4eb529c..90529e5 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -96,6 +96,8 @@
private static final boolean DBG = false;
private static final Pattern scanResultPattern = Pattern.compile("\t+");
private final WifiStateTracker mWifiStateTracker;
+ /* TODO: fetch a configurable interface */
+ private static final String SOFTAP_IFACE = "wl0.1";
private Context mContext;
private int mWifiApState;
@@ -308,13 +310,17 @@
}
} catch (Exception e) {
Slog.e(TAG, "Error configuring interface " + intf + ", :" + e);
+ try {
+ nwService.stopAccessPoint();
+ } catch (Exception ee) {
+ Slog.e(TAG, "Could not stop AP, :" + ee);
+ }
setWifiApEnabledState(WIFI_AP_STATE_FAILED, 0, DriverAction.DRIVER_UNLOAD);
return;
}
if(mCm.tether(intf) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
Slog.e(TAG, "Error tethering "+intf);
- setWifiApEnabledState(WIFI_AP_STATE_FAILED, 0, DriverAction.DRIVER_UNLOAD);
}
break;
}
@@ -578,9 +584,10 @@
}
/**
- * see {@link android.net.wifi.WifiManager#startAccessPoint(WifiConfiguration)}
+ * see {@link android.net.wifi.WifiManager#setWifiApEnabled(WifiConfiguration, boolean)}
* @param wifiConfig SSID, security and channel details as
* part of WifiConfiguration
+ * @param enabled, true to enable and false to disable
* @return {@code true} if the start operation was
* started or is already in the queue.
*/
@@ -652,11 +659,16 @@
if(enable && (wifiConfig != null)) {
try {
persistApConfiguration(wifiConfig);
- nwService.stopAccessPoint();
- nwService.startAccessPoint(wifiConfig, mWifiStateTracker.getInterfaceName());
+ nwService.setAccessPoint(wifiConfig, mWifiStateTracker.getInterfaceName(),
+ SOFTAP_IFACE);
return true;
} catch(Exception e) {
Slog.e(TAG, "Exception in nwService during AP restart");
+ try {
+ nwService.stopAccessPoint();
+ } catch (Exception ee) {
+ Slog.e(TAG, "Could not stop AP, :" + ee);
+ }
setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid, DriverAction.DRIVER_UNLOAD);
return false;
}
@@ -692,7 +704,8 @@
}
try {
- nwService.startAccessPoint(wifiConfig, mWifiStateTracker.getInterfaceName());
+ nwService.startAccessPoint(wifiConfig, mWifiStateTracker.getInterfaceName(),
+ SOFTAP_IFACE);
} catch(Exception e) {
Slog.e(TAG, "Exception in startAccessPoint()");
setWifiApEnabledState(WIFI_AP_STATE_FAILED, uid, DriverAction.DRIVER_UNLOAD);
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 44e0dad..55840e2 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -991,10 +991,10 @@
// asu = 0 (-113dB or less) is very weak
// signal, its better to show 0 bars to the user in such cases.
// asu = 99 is a special case, where the signal strength is unknown.
- if (asu <= 0 || asu == 99) iconLevel = 0;
- else if (asu >= 16) iconLevel = 4;
+ if (asu <= 2 || asu == 99) iconLevel = 0;
+ else if (asu >= 12) iconLevel = 4;
else if (asu >= 8) iconLevel = 3;
- else if (asu >= 4) iconLevel = 2;
+ else if (asu >= 5) iconLevel = 2;
else iconLevel = 1;
// Though mPhone is a Manager, this call is not an IPC
diff --git a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
index 009c0f2d93..b581192 100755
--- a/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/PackageManagerTests.java
@@ -86,8 +86,7 @@
fail(errMsg);
}
void failStr(Exception e) {
- Log.w(TAG, "e.getMessage="+e.getMessage());
- Log.w(TAG, "e="+e);
+ failStr(e.getMessage());
}
@Override
@@ -297,6 +296,17 @@
private static final int INSTALL_LOC_INT = 1;
private static final int INSTALL_LOC_SD = 2;
private static final int INSTALL_LOC_ERR = -1;
+ private int checkDefaultPolicy(long pkgLen) {
+ // Check for free memory internally
+ if (checkInt(pkgLen)) {
+ return INSTALL_LOC_INT;
+ }
+ // Check for free memory externally
+ if (checkSd(pkgLen)) {
+ return INSTALL_LOC_SD;
+ }
+ return INSTALL_LOC_ERR;
+ }
private int getInstallLoc(int flags, int expInstallLocation, long pkgLen) {
// Flags explicitly over ride everything else.
if ((flags & PackageManager.INSTALL_FORWARD_LOCK) != 0 ) {
@@ -324,15 +334,7 @@
return INSTALL_LOC_ERR;
}
if (expInstallLocation == PackageInfo.INSTALL_LOCATION_AUTO) {
- // Check for free memory internally
- if (checkInt(pkgLen)) {
- return INSTALL_LOC_INT;
- }
- // Check for free memory externally
- if (checkSd(pkgLen)) {
- return INSTALL_LOC_SD;
- }
- return INSTALL_LOC_ERR;
+ return checkDefaultPolicy(pkgLen);
}
// Check for settings preference.
boolean checkSd = false;
@@ -359,19 +361,9 @@
return INSTALL_LOC_SD;
}
return INSTALL_LOC_ERR;
- } else if (userPref == APP_INSTALL_AUTO) {
- if (checkInt(pkgLen)) {
- return INSTALL_LOC_INT;
- }
- // Check for free memory externally
- if (checkSd(pkgLen)) {
- return INSTALL_LOC_SD;
- }
- return INSTALL_LOC_ERR;
-
}
- }
- return INSTALL_LOC_ERR;
+ }
+ return checkDefaultPolicy(pkgLen);
}
private void assertInstall(PackageParser.Package pkg, int flags, int expInstallLocation) {
@@ -434,7 +426,7 @@
private InstallParams sampleInstallFromRawResource(int flags, boolean cleanUp) {
return installFromRawResource("install.apk", R.raw.install, flags, cleanUp,
- false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
+ false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
static final String PERM_PACKAGE = "package";
@@ -1114,7 +1106,7 @@
public void testManifestInstallLocationUnspecified() {
installFromRawResource("install.apk", R.raw.install_loc_unspecified,
- 0, true, false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
+ 0, true, false, -1, PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
public void testManifestInstallLocationFwdLockedFlagSdcard() {
@@ -1122,7 +1114,7 @@
PackageManager.INSTALL_FORWARD_LOCK |
PackageManager.INSTALL_EXTERNAL, true, true,
PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION,
- PackageInfo.INSTALL_LOCATION_AUTO);
+ PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
}
public void testManifestInstallLocationFwdLockedSdcard() {
@@ -1178,12 +1170,12 @@
public void testManifestInstallLocationReplaceInternalSdcard() {
int iFlags = 0;
- int iApk = R.raw.install_loc_unspecified;
+ int iApk = R.raw.install_loc_internal;
int rFlags = 0;
int rApk = R.raw.install_loc_sdcard;
InstallParams ip = installFromRawResource("install.apk", iApk,
iFlags, false,
- false, -1, PackageInfo.INSTALL_LOCATION_AUTO);
+ false, -1, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
GenericReceiver receiver = new ReplaceReceiver(ip.pkg.packageName);
int replaceFlags = rFlags | PackageManager.INSTALL_REPLACE_EXISTING;
try {
@@ -1855,21 +1847,28 @@
* The following set of tests check install location for existing
* application based on user setting.
*/
- private void setExistingXUserX(int userSetting, int iFlags) {
+ private int getExpectedInstallLocation(int userSetting) {
+ int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ boolean enable = getUserSettingSetInstallLocation();
+ if (enable) {
+ if (userSetting == PackageHelper.APP_INSTALL_AUTO) {
+ iloc = PackageInfo.INSTALL_LOCATION_AUTO;
+ } else if (userSetting == PackageHelper.APP_INSTALL_EXTERNAL) {
+ iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
+ } else if (userSetting == PackageHelper.APP_INSTALL_INTERNAL) {
+ iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
+ }
+ }
+ return iloc;
+ }
+ private void setExistingXUserX(int userSetting, int iFlags, int iloc) {
int rFlags = PackageManager.INSTALL_REPLACE_EXISTING;
// First install.
installFromRawResource("install.apk", R.raw.install,
iFlags,
false,
false, -1,
- -1);
- // Watch out for this.
- int iloc = PackageInfo.INSTALL_LOCATION_AUTO;
- if ((iFlags & PackageManager.INSTALL_INTERNAL) != 0) {
- iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
- } else if ((iFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
- iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
- }
+ PackageInfo.INSTALL_LOCATION_UNSPECIFIED);
int origSetting = getInstallLoc();
try {
// Set user setting
@@ -1887,49 +1886,56 @@
public void testExistingIUserI() {
int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
int iFlags = PackageManager.INSTALL_INTERNAL;
- setExistingXUserX(userSetting, iFlags);
+ setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
}
public void testExistingIUserE() {
int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
int iFlags = PackageManager.INSTALL_INTERNAL;
- setExistingXUserX(userSetting, iFlags);
+ setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
}
public void testExistingIUserA() {
int userSetting = PackageHelper.APP_INSTALL_AUTO;
int iFlags = PackageManager.INSTALL_INTERNAL;
- setExistingXUserX(userSetting, iFlags);
+ setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY);
}
public void testExistingEUserI() {
int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
int iFlags = PackageManager.INSTALL_EXTERNAL;
- setExistingXUserX(userSetting, iFlags);
+ setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
}
public void testExistingEUserE() {
int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
int iFlags = PackageManager.INSTALL_EXTERNAL;
- setExistingXUserX(userSetting, iFlags);
+ setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
}
public void testExistingEUserA() {
int userSetting = PackageHelper.APP_INSTALL_AUTO;
int iFlags = PackageManager.INSTALL_EXTERNAL;
- setExistingXUserX(userSetting, iFlags);
+ setExistingXUserX(userSetting, iFlags, PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL);
}
/*
* The following set of tests verify that the user setting defines
* the install location.
*
*/
- private void setUserX(int userSetting) {
- int origSetting = getInstallLoc();
- int iloc = PackageInfo.INSTALL_LOCATION_AUTO;
- if (userSetting == PackageHelper.APP_INSTALL_AUTO) {
- iloc = PackageInfo.INSTALL_LOCATION_AUTO;
- } else if (userSetting == PackageHelper.APP_INSTALL_EXTERNAL) {
- iloc = PackageInfo.INSTALL_LOCATION_PREFER_EXTERNAL;
- } else if (userSetting == PackageHelper.APP_INSTALL_INTERNAL) {
- iloc = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY;
- }
+ private boolean getUserSettingSetInstallLocation() {
try {
+ return Settings.System.getInt(mContext.getContentResolver(), Settings.System.SET_INSTALL_LOCATION) != 0;
+
+ } catch (SettingNotFoundException e1) {
+ }
+ return false;
+ }
+
+ private void setUserSettingSetInstallLocation(boolean value) {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.SET_INSTALL_LOCATION, value ? 1 : 0);
+ }
+ private void setUserX(boolean enable, int userSetting, int iloc) {
+ boolean origUserSetting = getUserSettingSetInstallLocation();
+ int origSetting = getInstallLoc();
+ try {
+ setUserSettingSetInstallLocation(enable);
// Set user setting
setInstallLoc(userSetting);
// Replace now
@@ -1939,20 +1945,44 @@
false, -1,
iloc);
} finally {
+ // Restore original setting
+ setUserSettingSetInstallLocation(origUserSetting);
setInstallLoc(origSetting);
}
}
public void testUserI() {
int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
- setUserX(userSetting);
+ int iloc = getExpectedInstallLocation(userSetting);
+ setUserX(true, userSetting, iloc);
}
public void testUserE() {
int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
- setUserX(userSetting);
+ int iloc = getExpectedInstallLocation(userSetting);
+ setUserX(true, userSetting, iloc);
}
public void testUserA() {
int userSetting = PackageHelper.APP_INSTALL_AUTO;
- setUserX(userSetting);
+ int iloc = getExpectedInstallLocation(userSetting);
+ setUserX(true, userSetting, iloc);
+ }
+ /*
+ * The following set of tests turn on/off the basic
+ * user setting for turning on install location.
+ */
+ public void testUserPrefOffUserI() {
+ int userSetting = PackageHelper.APP_INSTALL_INTERNAL;
+ int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ setUserX(false, userSetting, iloc);
+ }
+ public void testUserPrefOffUserE() {
+ int userSetting = PackageHelper.APP_INSTALL_EXTERNAL;
+ int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ setUserX(false, userSetting, iloc);
+ }
+ public void testUserPrefOffA() {
+ int userSetting = PackageHelper.APP_INSTALL_AUTO;
+ int iloc = PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
+ setUserX(false, userSetting, iloc);
}
static final String BASE_PERMISSIONS_DEFINED[] = new String[] {
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index b668bd0..d51d17a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -91,7 +91,6 @@
ignoreResultList.add("http/tests/appcache/disabled.html"); // not found
ignoreResultList.add("http/tests/appcache/empty-manifest.html"); // flaky
ignoreResultList.add("http/tests/appcache/foreign-iframe-main.html"); // flaky - skips states
- ignoreResultList.add("http/tests/appcache/local-content.html"); // text diff
ignoreResultList.add("http/tests/appcache/max-size.html"); // no layoutTestController.setAppCacheMaximumSize
ignoreResultList.add("http/tests/appcache/manifest-with-empty-file.html"); // flaky
ignoreResultList.add("http/tests/appcache/whitelist-wildcard.html"); // file not found
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index 08530a0..c8b6837 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -37,12 +37,12 @@
mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false),
mUpdate(false), mExtending(false),
mRequireLocalization(false), mPseudolocalize(false),
- mUTF8(false), mEncodingSpecified(false), mValues(false),
+ mWantUTF16(false), mValues(false),
mCompressionMethod(0), mOutputAPKFile(NULL),
mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
mAutoAddOverlay(false), mAssetSourceDir(NULL), mProguardFile(NULL),
mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
- mRClassDir(NULL), mResourceIntermediatesDir(NULL),
+ mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL),
mArgc(0), mArgv(NULL)
@@ -77,10 +77,8 @@
void setRequireLocalization(bool val) { mRequireLocalization = val; }
bool getPseudolocalize(void) const { return mPseudolocalize; }
void setPseudolocalize(bool val) { mPseudolocalize = val; }
- bool getUTF8(void) const { return mUTF8; }
- void setUTF8(bool val) { mUTF8 = val; }
- bool getEncodingSpecified(void) const { return mEncodingSpecified; }
- void setEncodingSpecified(bool val) { mEncodingSpecified = val; }
+ bool getWantUTF16(void) const { return mWantUTF16; }
+ void setWantUTF16(bool val) { mWantUTF16 = val; }
bool getValues(void) const { return mValues; }
void setValues(bool val) { mValues = val; }
int getCompressionMethod(void) const { return mCompressionMethod; }
@@ -122,13 +120,10 @@
const android::Vector<const char*>& getNoCompressExtensions() const { return mNoCompressExtensions; }
void addNoCompressExtension(const char* ext) { mNoCompressExtensions.add(ext); }
+ const char* getManifestMinSdkVersion() const { return mManifestMinSdkVersion; }
+ void setManifestMinSdkVersion(const char* val) { mManifestMinSdkVersion = val; }
const char* getMinSdkVersion() const { return mMinSdkVersion; }
- void setMinSdkVersion(const char* val) {
- mMinSdkVersion = val;
- if (!mEncodingSpecified) {
- setUTF8(isUTF8Available());
- }
- }
+ void setMinSdkVersion(const char* val) { mMinSdkVersion = val; }
const char* getTargetSdkVersion() const { return mTargetSdkVersion; }
void setTargetSdkVersion(const char* val) { mTargetSdkVersion = val; }
const char* getMaxSdkVersion() const { return mMaxSdkVersion; }
@@ -167,6 +162,34 @@
void setPackageCount(int val) { mPackageCount = val; }
#endif
+ /* UTF-8 is only available on APIs 7 or above or
+ * SDK levels that have code names.
+ */
+ bool isUTF8Available() {
+ /* If the application specifies a minSdkVersion in the manifest
+ * then use that. Otherwise, check what the user specified on
+ * the command line. If neither, it's not available since
+ * the minimum SDK version is assumed to be 1.
+ */
+ const char *minVer;
+ if (mManifestMinSdkVersion != NULL) {
+ minVer = mManifestMinSdkVersion;
+ } else if (mMinSdkVersion != NULL) {
+ minVer = mMinSdkVersion;
+ } else {
+ return false;
+ }
+
+ char *end;
+ int minSdkNum = (int)strtol(minVer, &end, 0);
+ if (*end == '\0') {
+ if (minSdkNum < 7) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private:
/* commands & modifiers */
Command mCmd;
@@ -179,8 +202,7 @@
bool mExtending;
bool mRequireLocalization;
bool mPseudolocalize;
- bool mUTF8;
- bool mEncodingSpecified;
+ bool mWantUTF16;
bool mValues;
int mCompressionMethod;
bool mJunkPath;
@@ -200,6 +222,7 @@
android::Vector<const char*> mNoCompressExtensions;
android::Vector<const char*> mResourceSourceDirs;
+ const char* mManifestMinSdkVersion;
const char* mMinSdkVersion;
const char* mTargetSdkVersion;
const char* mMaxSdkVersion;
@@ -216,19 +239,6 @@
int mPackageCount;
#endif
- /* UTF-8 is only available on APIs 7 or above or
- * SDK levels that have code names.
- */
- bool isUTF8Available() {
- char *end;
- int minSdkNum = (int)strtol(mMinSdkVersion, &end, 0);
- if (*end == '\0') {
- if (minSdkNum < 7) {
- return false;
- }
- }
- return true;
- }
};
#endif // __BUNDLE_H
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index dd98c85..b0c6e39 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -446,8 +446,7 @@
}
bundle.setCustomPackage(argv[0]);
} else if (strcmp(cp, "-utf16") == 0) {
- bundle.setEncodingSpecified(true);
- bundle.setUTF8(false);
+ bundle.setWantUTF16(true);
} else if (strcmp(cp, "-rename-manifest-package") == 0) {
argc--;
argv++;
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index c0ebb59..a8ac2ec 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -226,7 +226,7 @@
if (minSdkIndex >= 0) {
const uint16_t* minSdk16 = block.getAttributeStringValue(minSdkIndex, &len);
const char* minSdk8 = strdup(String8(minSdk16).string());
- bundle->setMinSdkVersion(minSdk8);
+ bundle->setManifestMinSdkVersion(minSdk8);
}
}
}
@@ -611,7 +611,8 @@
const String16 attr(attr8);
if (node->getAttribute(ns, attr) != NULL) {
- fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s)\n",
+ fprintf(stderr, "Warning: AndroidManifest.xml already defines %s (in %s);"
+ " using existing value in manifest.\n",
String8(attr).string(), String8(ns).string());
return;
}
@@ -768,7 +769,13 @@
// Standard flags for compiled XML and optional UTF-8 encoding
int xmlFlags = XML_COMPILE_STANDARD_RESOURCE;
- if (bundle->getUTF8()) {
+
+ /* Only enable UTF-8 if the caller of aapt didn't specifically
+ * request UTF-16 encoding and the parameters of this package
+ * allow UTF-8 to be used.
+ */
+ if (!bundle->getWantUTF16()
+ && bundle->isUTF8Available()) {
xmlFlags |= XML_COMPILE_UTF8;
}
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index ab5e937..66db450 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -2527,9 +2527,11 @@
const size_t N = mOrderedPackages.size();
size_t pi;
+ bool useUTF8 = !bundle->getWantUTF16() && bundle->isUTF8Available();
+
// Iterate through all data, collecting all values (strings,
// references, etc).
- StringPool valueStrings = StringPool(false, bundle->getUTF8());
+ StringPool valueStrings = StringPool(false, useUTF8);
for (pi=0; pi<N; pi++) {
sp<Package> p = mOrderedPackages.itemAt(pi);
if (p->getTypes().size() == 0) {
@@ -2537,8 +2539,8 @@
continue;
}
- StringPool typeStrings = StringPool(false, bundle->getUTF8());
- StringPool keyStrings = StringPool(false, bundle->getUTF8());
+ StringPool typeStrings = StringPool(false, useUTF8);
+ StringPool keyStrings = StringPool(false, useUTF8);
const size_t N = p->getOrderedTypes().size();
for (size_t ti=0; ti<N; ti++) {
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index 9339428..abae65d 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -1074,7 +1074,11 @@
break;
case EVENT_DEFERRED_RECONNECT:
- String BSSID = msg.obj.toString();
+ /**
+ * mLastBssid can be null when there is a reconnect
+ * request on the first BSSID we connect to
+ */
+ String BSSID = (msg.obj != null) ? msg.obj.toString() : null;
/**
* If we've exceeded the maximum number of retries for reconnecting
* to a given network, blacklist the BSSID to allow a connection attempt on