Merge "Add PendingIntent and IntentSender APIs to get user handle." into jb-mr1-dev
diff --git a/api/17.txt b/api/17.txt
index 984b844..c43802f 100644
--- a/api/17.txt
+++ b/api/17.txt
@@ -9802,7 +9802,7 @@
method public float getZ();
}
- public class Sensor {
+ public final class Sensor {
method public float getMaximumRange();
method public int getMinDelay();
method public java.lang.String getName();
diff --git a/api/current.txt b/api/current.txt
index dbe4453..6a32efe 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5264,6 +5264,7 @@
method public abstract int checkUriPermission(android.net.Uri, int, int, int);
method public abstract int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public abstract deprecated void clearWallpaper() throws java.io.IOException;
+ method public abstract android.content.Context createConfigurationContext(android.content.res.Configuration);
method public abstract android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public abstract java.lang.String[] databaseList();
method public abstract boolean deleteDatabase(java.lang.String);
@@ -5408,6 +5409,7 @@
method public int checkUriPermission(android.net.Uri, int, int, int);
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public void clearWallpaper() throws java.io.IOException;
+ method public android.content.Context createConfigurationContext(android.content.res.Configuration);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
method public boolean deleteDatabase(java.lang.String);
@@ -9852,7 +9854,7 @@
method public float getZ();
}
- public class Sensor {
+ public final class Sensor {
method public float getMaximumRange();
method public int getMinDelay();
method public java.lang.String getName();
@@ -13214,7 +13216,6 @@
field public java.lang.String capabilities;
field public int frequency;
field public int level;
- field public long timestamp;
}
public final class SupplicantState extends java.lang.Enum implements android.os.Parcelable {
@@ -17238,9 +17239,11 @@
field public static final java.lang.String DURATION = "duration";
field public static final int INCOMING_TYPE = 1; // 0x1
field public static final java.lang.String IS_READ = "is_read";
+ field public static final java.lang.String LIMIT_PARAM_KEY = "limit";
field public static final int MISSED_TYPE = 3; // 0x3
field public static final java.lang.String NEW = "new";
field public static final java.lang.String NUMBER = "number";
+ field public static final java.lang.String OFFSET_PARAM_KEY = "offset";
field public static final int OUTGOING_TYPE = 2; // 0x2
field public static final java.lang.String TYPE = "type";
}
@@ -21151,6 +21154,7 @@
method public int checkUriPermission(android.net.Uri, int, int, int);
method public int checkUriPermission(android.net.Uri, java.lang.String, java.lang.String, int, int, int);
method public void clearWallpaper();
+ method public android.content.Context createConfigurationContext(android.content.res.Configuration);
method public android.content.Context createPackageContext(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method public java.lang.String[] databaseList();
method public boolean deleteDatabase(java.lang.String);
@@ -23355,6 +23359,7 @@
public class ContextThemeWrapper extends android.content.ContextWrapper {
ctor public ContextThemeWrapper();
ctor public ContextThemeWrapper(android.content.Context, int);
+ method public void applyOverrideConfiguration(android.content.res.Configuration);
method protected void onApplyThemeResource(android.content.res.Resources.Theme, int, boolean);
}
diff --git a/core/java/android/animation/TimeAnimator.java b/core/java/android/animation/TimeAnimator.java
index 088d20d..f9aa00e 100644
--- a/core/java/android/animation/TimeAnimator.java
+++ b/core/java/android/animation/TimeAnimator.java
@@ -13,6 +13,12 @@
private long mPreviousTime = -1;
@Override
+ public void start() {
+ mPreviousTime = -1;
+ super.start();
+ }
+
+ @Override
boolean animationFrame(long currentTime) {
if (mListener != null) {
long totalTime = currentTime - mStartTime;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index bb35ddd..0789c60 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1471,13 +1471,25 @@
private static class ResourcesKey {
final private String mResDir;
+ final private Configuration mOverrideConfiguration;
final private float mScale;
final private int mHash;
- ResourcesKey(String resDir, float scale) {
+ ResourcesKey(String resDir, Configuration overrideConfiguration, float scale) {
mResDir = resDir;
+ if (overrideConfiguration != null) {
+ if (Configuration.EMPTY.equals(overrideConfiguration)) {
+ overrideConfiguration = null;
+ }
+ }
+ mOverrideConfiguration = overrideConfiguration;
mScale = scale;
- mHash = mResDir.hashCode() << 2 + (int) (mScale * 2);
+ int hash = 17;
+ hash = 31 * hash + mResDir.hashCode();
+ hash = 31 * hash + (mOverrideConfiguration != null
+ ? mOverrideConfiguration.hashCode() : 0);
+ hash = 31 * hash + Float.floatToIntBits(mScale);
+ mHash = hash;
}
@Override
@@ -1491,7 +1503,21 @@
return false;
}
ResourcesKey peer = (ResourcesKey) obj;
- return mResDir.equals(peer.mResDir) && mScale == peer.mScale;
+ if (!mResDir.equals(peer.mResDir)) {
+ return false;
+ }
+ if (mOverrideConfiguration != peer.mOverrideConfiguration) {
+ if (mOverrideConfiguration == null || peer.mOverrideConfiguration == null) {
+ return false;
+ }
+ if (!mOverrideConfiguration.equals(peer.mOverrideConfiguration)) {
+ return false;
+ }
+ }
+ if (mScale != peer.mScale) {
+ return false;
+ }
+ return true;
}
}
@@ -1562,8 +1588,10 @@
* @param compInfo the compability info. It will use the default compatibility info when it's
* null.
*/
- Resources getTopLevelResources(String resDir, CompatibilityInfo compInfo) {
- ResourcesKey key = new ResourcesKey(resDir, compInfo.applicationScale);
+ Resources getTopLevelResources(String resDir, Configuration overrideConfiguration,
+ CompatibilityInfo compInfo) {
+ ResourcesKey key = new ResourcesKey(resDir, overrideConfiguration,
+ compInfo.applicationScale);
Resources r;
synchronized (mPackages) {
// Resources is app scale dependent.
@@ -1595,13 +1623,20 @@
//Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics);
DisplayMetrics metrics = getDisplayMetricsLocked(null, false);
- r = new Resources(assets, metrics, getConfiguration(), compInfo);
+ Configuration config;
+ if (key.mOverrideConfiguration != null) {
+ config = new Configuration(getConfiguration());
+ config.updateFrom(key.mOverrideConfiguration);
+ } else {
+ config = getConfiguration();
+ }
+ r = new Resources(assets, metrics, config, compInfo);
if (false) {
Slog.i(TAG, "Created app resources " + resDir + " " + r + ": "
+ r.getConfiguration() + " appScale="
+ r.getCompatibilityInfo().applicationScale);
}
-
+
synchronized (mPackages) {
WeakReference<Resources> wr = mActiveResources.get(key);
Resources existing = wr != null ? wr.get() : null;
@@ -1621,8 +1656,10 @@
/**
* Creates the top level resources for the given package.
*/
- Resources getTopLevelResources(String resDir, LoadedApk pkgInfo) {
- return getTopLevelResources(resDir, pkgInfo.mCompatibilityInfo.get());
+ Resources getTopLevelResources(String resDir, Configuration overrideConfiguration,
+ LoadedApk pkgInfo) {
+ return getTopLevelResources(resDir, overrideConfiguration,
+ pkgInfo.mCompatibilityInfo.get());
}
final Handler getHandler() {
@@ -3675,18 +3712,28 @@
ApplicationPackageManager.configurationChanged();
//Slog.i(TAG, "Configuration changed in " + currentPackageName());
-
- Iterator<WeakReference<Resources>> it =
- mActiveResources.values().iterator();
- //Iterator<Map.Entry<String, WeakReference<Resources>>> it =
- // mActiveResources.entrySet().iterator();
+
+ Configuration tmpConfig = null;
+
+ Iterator<Map.Entry<ResourcesKey, WeakReference<Resources>>> it =
+ mActiveResources.entrySet().iterator();
while (it.hasNext()) {
- WeakReference<Resources> v = it.next();
- Resources r = v.get();
+ Map.Entry<ResourcesKey, WeakReference<Resources>> entry = it.next();
+ Resources r = entry.getValue().get();
if (r != null) {
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Changing resources "
+ r + " config to: " + config);
- r.updateConfiguration(config, dm, compat);
+ Configuration override = entry.getKey().mOverrideConfiguration;
+ if (override != null) {
+ if (tmpConfig == null) {
+ tmpConfig = new Configuration();
+ }
+ tmpConfig.setTo(config);
+ tmpConfig.updateFrom(override);
+ r.updateConfiguration(tmpConfig, dm, compat);
+ } else {
+ r.updateConfiguration(config, dm, compat);
+ }
//Slog.i(TAG, "Updated app resources " + v.getKey()
// + " " + r + ": " + r.getConfiguration());
} else {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 2face4c..9b59e2c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -713,7 +713,7 @@
}
Resources r = mContext.mMainThread.getTopLevelResources(
app.uid == Process.myUid() ? app.sourceDir
- : app.publicSourceDir, mContext.mPackageInfo);
+ : app.publicSourceDir, null, mContext.mPackageInfo);
if (r != null) {
return r;
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4496ce8..1ef14eb 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -37,6 +37,7 @@
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.CompatibilityInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
@@ -525,7 +526,7 @@
@Override
public AssetManager getAssets() {
- return mResources.getAssets();
+ return getResources().getAssets();
}
@Override
@@ -1591,6 +1592,16 @@
}
@Override
+ public Context createConfigurationContext(Configuration overrideConfiguration) {
+ ContextImpl c = new ContextImpl();
+ c.init(mPackageInfo, null, mMainThread);
+ c.mResources = mMainThread.getTopLevelResources(
+ mPackageInfo.getResDir(), overrideConfiguration,
+ mResources.getCompatibilityInfo());
+ return c;
+ }
+
+ @Override
public boolean isRestricted() {
return mRestricted;
}
@@ -1659,12 +1670,11 @@
" compatiblity info:" + container.getDisplayMetrics());
}
mResources = mainThread.getTopLevelResources(
- mPackageInfo.getResDir(), container.getCompatibilityInfo());
+ mPackageInfo.getResDir(), null, container.getCompatibilityInfo());
}
mMainThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread);
-
- setActivityToken(activityToken);
+ mActivityToken = activityToken;
}
final void init(Resources resources, ActivityThread mainThread) {
@@ -1691,10 +1701,6 @@
return mReceiverRestrictedContext = new ReceiverRestrictedContext(getOuterContext());
}
- final void setActivityToken(IBinder token) {
- mActivityToken = token;
- }
-
final void setOuterContext(Context context) {
mOuterContext = context;
}
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 688cdfd..074d343 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -30,4 +30,5 @@
List<ResolveInfo> getGlobalSearchActivities();
ComponentName getGlobalSearchActivity();
ComponentName getWebSearchActivity();
+ ComponentName getAssistIntent(int userHandle);
}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index be4b284..f4195d6 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -471,7 +471,7 @@
public Resources getResources(ActivityThread mainThread) {
if (mResources == null) {
- mResources = mainThread.getTopLevelResources(mResDir, this);
+ mResources = mainThread.getTopLevelResources(mResDir, null, this);
}
return mResources;
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b2e69de..cb83dc2 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -897,12 +897,16 @@
* Builder class for {@link Notification} objects.
*
* Provides a convenient way to set the various fields of a {@link Notification} and generate
- * content views using the platform's notification layout template.
+ * content views using the platform's notification layout template. If your app supports
+ * versions of Android as old as API level 4, you can instead use
+ * {@link android.support.v4.app.NotificationCompat.Builder NotificationCompat.Builder},
+ * available in the <a href="{@docRoot}tools/extras/support-library.html">Android Support
+ * library</a>.
*
- * Example:
+ * <p>Example:
*
* <pre class="prettyprint">
- * Notification noti = new Notification.Builder()
+ * Notification noti = new Notification.Builder(mContext)
* .setContentTitle("New mail from " + sender.toString())
* .setContentText(subject)
* .setSmallIcon(R.drawable.new_mail)
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index d1d5131..b8c9937 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -31,6 +31,7 @@
import android.os.Handler;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.UserId;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;
@@ -845,14 +846,28 @@
*
* @hide
*/
- public static final Intent getAssistIntent(Context context) {
- PackageManager pm = context.getPackageManager();
- Intent intent = new Intent(Intent.ACTION_ASSIST);
- ComponentName component = intent.resolveActivity(pm);
- if (component != null) {
- intent.setComponent(component);
+ public Intent getAssistIntent(Context context) {
+ return getAssistIntent(context, UserId.myUserId());
+ }
+
+ /**
+ * Gets an intent for launching installed assistant activity, or null if not available.
+ * @return The assist intent.
+ *
+ * @hide
+ */
+ public Intent getAssistIntent(Context context, int userHandle) {
+ try {
+ ComponentName comp = mService.getAssistIntent(userHandle);
+ if (comp == null) {
+ return null;
+ }
+ Intent intent = new Intent(Intent.ACTION_ASSIST);
+ intent.setComponent(comp);
return intent;
+ } catch (RemoteException re) {
+ Log.e(TAG, "getAssistIntent() failed: " + re);
+ return null;
}
- return null;
}
}
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ceaf17e..17d404d 100755
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -504,7 +504,10 @@
* immediate error
*/
public boolean enable() {
- boolean enabled = false;
+ if (isEnabled() == true){
+ if (DBG) Log.d(TAG, "enable(): BT is already enabled..!");
+ return true;
+ }
try {
return mManagerService.enable();
} catch (RemoteException e) {Log.e(TAG, "", e);}
@@ -1246,8 +1249,14 @@
* @hide
*/
public boolean enableNoAutoConnect() {
- // TODO avoid auto-connect in the new stack.
- return enable();
+ if (isEnabled() == true){
+ if (DBG) Log.d(TAG, "enableNoAutoConnect(): BT is already enabled..!");
+ return true;
+ }
+ try {
+ return mManagerService.enableNoAutoConnect();
+ } catch (RemoteException e) {Log.e(TAG, "", e);}
+ return false;
}
/**
diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl
old mode 100644
new mode 100755
index f82da82..de8fe91
--- a/core/java/android/bluetooth/IBluetoothManager.aidl
+++ b/core/java/android/bluetooth/IBluetoothManager.aidl
@@ -21,6 +21,7 @@
void unregisterStateChangeCallback(in IBluetoothStateChangeCallback callback);
boolean isEnabled();
boolean enable();
+ boolean enableNoAutoConnect();
boolean disable(boolean persist);
String getAddress();
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index bf60a96..a90142a 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -19,6 +19,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.DatabaseErrorHandler;
@@ -2445,6 +2446,23 @@
int flags) throws PackageManager.NameNotFoundException;
/**
+ * Return a new Context object for the current Context but whose resources
+ * are adjusted to match the given Configuration. Each call to this method
+ * returns a new instance of a Contex object; Context objects are not
+ * shared, however common state (ClassLoader, other Resources for the
+ * same configuration) may be so the Context itself can be fairly lightweight.
+ *
+ * @param overrideConfiguration A {@link Configuration} specifying what
+ * values to modify in the base Configuration of the original Context's
+ * resources. If the base configuration changes (such as due to an
+ * orientation change), the resources of this context will also change except
+ * for those that have been explicitly overridden with a value here.
+ *
+ * @return A Context for the application.
+ */
+ public abstract Context createConfigurationContext(Configuration overrideConfiguration);
+
+ /**
* Indicates whether this Context is restricted.
*
* @return True if this Context is restricted, false otherwise.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index ff4c9a1..fdf60ab 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -19,6 +19,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
@@ -533,6 +534,11 @@
}
@Override
+ public Context createConfigurationContext(Configuration overrideConfiguration) {
+ return mBase.createConfigurationContext(overrideConfiguration);
+ }
+
+ @Override
public boolean isRestricted() {
return mBase.isRestricted();
}
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index ea13a2a..52b6498 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -35,6 +35,9 @@
* <pre>Configuration config = getResources().getConfiguration();</pre>
*/
public final class Configuration implements Parcelable, Comparable<Configuration> {
+ /** @hide */
+ public static final Configuration EMPTY = new Configuration();
+
/**
* Current user preference for the scaling factor for fonts, relative
* to the base density scaling.
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index d2af3e9..7559f1e 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1121,8 +1121,8 @@
* Return a StyledAttributes holding the values defined by
* <var>Theme</var> which are listed in <var>attrs</var>.
*
- * <p>Be sure to call StyledAttributes.recycle() when you are done with
- * the array.
+ * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
+ * with the array.
*
* @param attrs The desired attributes.
*
@@ -1149,8 +1149,8 @@
* Return a StyledAttributes holding the values defined by the style
* resource <var>resid</var> which are listed in <var>attrs</var>.
*
- * <p>Be sure to call StyledAttributes.recycle() when you are done with
- * the array.
+ * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
+ * with the array.
*
* @param resid The desired style resource.
* @param attrs The desired attributes in the style.
@@ -1209,8 +1209,8 @@
* AttributeSet specifies a style class (through the "style" attribute),
* that style will be applied on top of the base attributes it defines.
*
- * <p>Be sure to call StyledAttributes.recycle() when you are done with
- * the array.
+ * <p>Be sure to call {@link TypedArray#recycle() TypedArray.recycle()} when you are done
+ * with the array.
*
* <p>When determining the final value of a particular attribute, there
* are four inputs that come into play:</p>
@@ -1435,9 +1435,12 @@
int configChanges = 0xfffffff;
if (config != null) {
mTmpConfig.setTo(config);
+ int density = config.densityDpi;
+ if (density == Configuration.DENSITY_DPI_UNDEFINED) {
+ density = mMetrics.noncompatDensityDpi;
+ }
if (mCompatibilityInfo != null) {
- mCompatibilityInfo.applyToConfiguration(mMetrics.noncompatDensityDpi,
- mTmpConfig);
+ mCompatibilityInfo.applyToConfiguration(density, mTmpConfig);
}
if (mTmpConfig.locale == null) {
mTmpConfig.locale = Locale.getDefault();
@@ -1448,6 +1451,10 @@
if (mConfiguration.locale == null) {
mConfiguration.locale = Locale.getDefault();
}
+ if (mConfiguration.densityDpi != Configuration.DENSITY_DPI_UNDEFINED) {
+ mMetrics.densityDpi = mConfiguration.densityDpi;
+ mMetrics.density = mConfiguration.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+ }
mMetrics.scaledDensity = mMetrics.density * mConfiguration.fontScale;
String locale = null;
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 281b843..7f3b6b9 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -691,7 +691,7 @@
}
/**
- * Give back a previously retrieved StyledAttributes, for later re-use.
+ * Give back a previously retrieved array, for later re-use.
*/
public void recycle() {
synchronized (mResources.mTmpValue) {
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 3c70dc6..e0c9d2c 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -26,7 +26,7 @@
* @see SensorEvent
*
*/
-public class Sensor {
+public final class Sensor {
/**
* A constant describing an accelerometer sensor type. See
@@ -202,4 +202,11 @@
mMaxRange = max;
mResolution = res;
}
+
+ @Override
+ public String toString() {
+ return "{Sensor name=\"" + mName + "\", vendor=\"" + mVendor + "\", version=" + mVersion
+ + ", type=" + mType + ", maxRange=" + mMaxRange + ", resolution=" + mResolution
+ + ", power=" + mPower + ", minDelay=" + mMinDelay + "}";
+ }
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 22b68bc..5dca67f 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -17,9 +17,6 @@
package android.provider;
-import com.android.internal.telephony.CallerInfo;
-import com.android.internal.telephony.PhoneConstants;
-
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
@@ -30,6 +27,9 @@
import android.provider.ContactsContract.DataUsageFeedback;
import android.text.TextUtils;
+import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.PhoneConstants;
+
/**
* The CallLog provider contains information about placed and received calls.
*/
@@ -59,6 +59,20 @@
Uri.parse("content://call_log/calls/filter");
/**
+ * Query parameter used to limit the number of call logs returned.
+ * <p>
+ * TYPE: integer
+ */
+ public static final String LIMIT_PARAM_KEY = "limit";
+
+ /**
+ * Query parameter used to specify the starting record to return.
+ * <p>
+ * TYPE: integer
+ */
+ public static final String OFFSET_PARAM_KEY = "offset";
+
+ /**
* An optional URI parameter which instructs the provider to allow the operation to be
* applied to voicemail records as well.
* <p>
diff --git a/core/java/android/server/search/SearchManagerService.java b/core/java/android/server/search/SearchManagerService.java
index a1f6735..b4f5e12 100644
--- a/core/java/android/server/search/SearchManagerService.java
+++ b/core/java/android/server/search/SearchManagerService.java
@@ -18,6 +18,9 @@
import com.android.internal.content.PackageMonitor;
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.AppGlobals;
import android.app.ISearchManager;
import android.app.SearchManager;
import android.app.SearchableInfo;
@@ -27,14 +30,18 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.ContentObserver;
import android.os.Binder;
import android.os.Process;
+import android.os.RemoteException;
import android.os.UserId;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseArray;
import java.util.List;
@@ -207,4 +214,48 @@
return getSearchables(UserId.getCallingUserId()).getWebSearchActivity();
}
+ @Override
+ public ComponentName getAssistIntent(int userHandle) {
+ try {
+ if (userHandle != UserId.getCallingUserId()) {
+ // Requesting a different user, make sure that they have the permission
+ if (ActivityManager.checkComponentPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+ Binder.getCallingUid(), -1, true)
+ == PackageManager.PERMISSION_GRANTED) {
+ // Translate to the current user id, if caller wasn't aware
+ if (userHandle == UserId.USER_CURRENT) {
+ long identity = Binder.clearCallingIdentity();
+ userHandle = ActivityManagerNative.getDefault().getCurrentUser().id;
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else {
+ String msg = "Permission Denial: "
+ + "Request to getAssistIntent for " + userHandle
+ + " but is calling from user " + UserId.getCallingUserId()
+ + "; this requires "
+ + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+ Slog.w(TAG, msg);
+ return null;
+ }
+ }
+ IPackageManager pm = AppGlobals.getPackageManager();
+ Intent assistIntent = new Intent(Intent.ACTION_ASSIST);
+ ResolveInfo info =
+ pm.resolveIntent(assistIntent,
+ assistIntent.resolveTypeIfNeeded(mContext.getContentResolver()),
+ PackageManager.MATCH_DEFAULT_ONLY, userHandle);
+ if (info != null) {
+ return new ComponentName(
+ info.activityInfo.applicationInfo.packageName,
+ info.activityInfo.name);
+ }
+ } catch (RemoteException re) {
+ // Local call
+ Log.e(TAG, "RemoteException in getAssistIntent: " + re);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception in getAssistIntent: " + e);
+ }
+ return null;
+ }
}
diff --git a/core/java/android/speech/tts/BlockingAudioTrack.java b/core/java/android/speech/tts/BlockingAudioTrack.java
index fcadad7..47e2129 100644
--- a/core/java/android/speech/tts/BlockingAudioTrack.java
+++ b/core/java/android/speech/tts/BlockingAudioTrack.java
@@ -67,12 +67,10 @@
private int mAudioBufferSize;
private int mBytesWritten = 0;
- private AudioTrack mAudioTrack;
+ // Need to be seen by stop() which can be called from another thread. mAudioTrack will be
+ // set to null only after waitAndRelease().
+ private volatile AudioTrack mAudioTrack;
private volatile boolean mStopped;
- // Locks the initialization / uninitialization of the audio track.
- // This is required because stop() will throw an illegal state exception
- // if called before init() or after mAudioTrack.release().
- private final Object mAudioTrackLock = new Object();
BlockingAudioTrack(int streamType, int sampleRate,
int audioFormat, int channelCount,
@@ -93,19 +91,21 @@
mStopped = false;
}
- public void init() {
+ public boolean init() {
AudioTrack track = createStreamingAudioTrack();
+ mAudioTrack = track;
- synchronized (mAudioTrackLock) {
- mAudioTrack = track;
+ if (track == null) {
+ return false;
+ } else {
+ return true;
}
}
public void stop() {
- synchronized (mAudioTrackLock) {
- if (mAudioTrack != null) {
- mAudioTrack.stop();
- }
+ AudioTrack track = mAudioTrack;
+ if (track != null) {
+ track.stop();
}
mStopped = true;
}
@@ -120,6 +120,12 @@
}
public void waitAndRelease() {
+ AudioTrack track = mAudioTrack;
+ if (track == null) {
+ if (DBG) Log.d(TAG, "Audio track null [duplicate call to waitAndRelease ?]");
+ return;
+ }
+
// For "small" audio tracks, we have to stop() them to make them mixable,
// else the audio subsystem will wait indefinitely for us to fill the buffer
// before rendering the track mixable.
@@ -129,11 +135,11 @@
if (mBytesWritten < mAudioBufferSize && !mStopped) {
if (DBG) {
Log.d(TAG, "Stopping audio track to flush audio, state was : " +
- mAudioTrack.getPlayState() + ",stopped= " + mStopped);
+ track.getPlayState() + ",stopped= " + mStopped);
}
mIsShortUtterance = true;
- mAudioTrack.stop();
+ track.stop();
}
// Block until the audio track is done only if we haven't stopped yet.
@@ -145,11 +151,9 @@
// The last call to AudioTrack.write( ) will return only after
// all data from the audioTrack has been sent to the mixer, so
// it's safe to release at this point.
- if (DBG) Log.d(TAG, "Releasing audio track [" + mAudioTrack.hashCode() + "]");
- synchronized (mAudioTrackLock) {
- mAudioTrack.release();
- mAudioTrack = null;
- }
+ if (DBG) Log.d(TAG, "Releasing audio track [" + track.hashCode() + "]");
+ track.release();
+ mAudioTrack = null;
}
diff --git a/core/java/android/speech/tts/FileSynthesisCallback.java b/core/java/android/speech/tts/FileSynthesisCallback.java
index 04c3377..3e33e8e 100644
--- a/core/java/android/speech/tts/FileSynthesisCallback.java
+++ b/core/java/android/speech/tts/FileSynthesisCallback.java
@@ -95,6 +95,22 @@
}
}
+ /**
+ * Checks whether a given file exists, and deletes it if it does.
+ */
+ private boolean maybeCleanupExistingFile(File file) {
+ if (file.exists()) {
+ Log.v(TAG, "File " + file + " exists, deleting.");
+ if (!file.delete()) {
+ Log.e(TAG, "Failed to delete " + file);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
@Override
public int getMaxBufferSize() {
return MAX_AUDIO_BUFFER_SIZE;
@@ -120,6 +136,11 @@
cleanUp();
throw new IllegalArgumentException("FileSynthesisRequest.start() called twice");
}
+
+ if (!maybeCleanupExistingFile(mFileName)) {
+ return TextToSpeech.ERROR;
+ }
+
mSampleRateInHz = sampleRateInHz;
mAudioFormat = audioFormat;
mChannelCount = channelCount;
@@ -166,6 +187,12 @@
public int done() {
if (DBG) Log.d(TAG, "FileSynthesisRequest.done()");
synchronized (mStateLock) {
+ if (mDone) {
+ if (DBG) Log.d(TAG, "Duplicate call to done()");
+ // This preserves existing behaviour. Earlier, if done was called twice
+ // we'd return ERROR because mFile == null and we'd add to logspam.
+ return TextToSpeech.ERROR;
+ }
if (mStopped) {
if (DBG) Log.d(TAG, "Request has been aborted.");
return TextToSpeech.ERROR;
diff --git a/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java b/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
index d299d70..e853c9e 100644
--- a/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
+++ b/core/java/android/speech/tts/SynthesisPlaybackQueueItem.java
@@ -87,7 +87,10 @@
dispatcher.dispatchOnStart();
- mAudioTrack.init();
+ if (!mAudioTrack.init()) {
+ dispatcher.dispatchOnError();
+ return;
+ }
try {
byte[] buffer = null;
@@ -242,4 +245,3 @@
}
}
}
-
diff --git a/core/java/android/speech/tts/TextToSpeechService.java b/core/java/android/speech/tts/TextToSpeechService.java
index 4c1a0af..d124e68 100644
--- a/core/java/android/speech/tts/TextToSpeechService.java
+++ b/core/java/android/speech/tts/TextToSpeechService.java
@@ -549,7 +549,7 @@
@Override
public boolean isValid() {
if (mText == null) {
- Log.wtf(TAG, "Got null text");
+ Log.e(TAG, "null synthesis text");
return false;
}
if (mText.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH) {
@@ -641,14 +641,6 @@
}
@Override
- public boolean isValid() {
- if (!super.isValid()) {
- return false;
- }
- return checkFile(mFile);
- }
-
- @Override
protected AbstractSynthesisCallback createSynthesisCallback() {
return new FileSynthesisCallback(mFile);
}
@@ -664,33 +656,6 @@
}
return status;
}
-
- /**
- * Checks that the given file can be used for synthesis output.
- */
- private boolean checkFile(File file) {
- try {
- if (file.exists()) {
- Log.v(TAG, "File " + file + " exists, deleting.");
- if (!file.delete()) {
- Log.e(TAG, "Failed to delete " + file);
- return false;
- }
- }
- if (!file.createNewFile()) {
- Log.e(TAG, "Can't create file " + file);
- return false;
- }
- if (!file.delete()) {
- Log.e(TAG, "Failed to delete " + file);
- return false;
- }
- return true;
- } catch (IOException e) {
- Log.e(TAG, "Can't use " + file + " due to exception " + e);
- return false;
- }
- }
}
private class AudioSpeechItem extends SpeechItem {
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index 270624c..83a70f3f 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -1042,9 +1042,14 @@
float avail, TruncateAt where,
boolean preserveLength,
EllipsizeCallback callback) {
+
+ final String ellipsis = (where == TruncateAt.END_SMALL) ?
+ Resources.getSystem().getString(R.string.ellipsis_two_dots) :
+ Resources.getSystem().getString(R.string.ellipsis);
+
return ellipsize(text, paint, avail, where, preserveLength, callback,
TextDirectionHeuristics.FIRSTSTRONG_LTR,
- (where == TruncateAt.END_SMALL) ? ELLIPSIS_TWO_DOTS : ELLIPSIS_NORMAL);
+ ellipsis);
}
/**
@@ -1700,9 +1705,4 @@
private static String[] EMPTY_STRING_ARRAY = new String[]{};
private static final char ZWNBS_CHAR = '\uFEFF';
-
- private static final String ELLIPSIS_NORMAL = Resources.getSystem().getString(
- R.string.ellipsis);
- private static final String ELLIPSIS_TWO_DOTS = Resources.getSystem().getString(
- R.string.ellipsis_two_dots);
}
diff --git a/core/java/android/view/ContextThemeWrapper.java b/core/java/android/view/ContextThemeWrapper.java
index 626f385..6c733f9 100644
--- a/core/java/android/view/ContextThemeWrapper.java
+++ b/core/java/android/view/ContextThemeWrapper.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
@@ -30,6 +31,8 @@
private int mThemeResource;
private Resources.Theme mTheme;
private LayoutInflater mInflater;
+ private Configuration mOverrideConfiguration;
+ private Resources mResources;
public ContextThemeWrapper() {
super(null);
@@ -45,6 +48,41 @@
super.attachBaseContext(newBase);
mBase = newBase;
}
+
+ /**
+ * Call to set an "override configuration" on this context -- this is
+ * a configuration that replies one or more values of the standard
+ * configuration that is applied to the context. See
+ * {@link Context#createConfigurationContext(Configuration)} for more
+ * information.
+ *
+ * <p>This method can only be called once, and must be called before any
+ * calls to {@link #getResources()} are made.
+ */
+ public void applyOverrideConfiguration(Configuration overrideConfiguration) {
+ if (mResources != null) {
+ throw new IllegalStateException("getResources() has already been called");
+ }
+ if (mOverrideConfiguration != null) {
+ throw new IllegalStateException("Override configuration has already been set");
+ }
+ mOverrideConfiguration = new Configuration(overrideConfiguration);
+ }
+
+ @Override
+ public Resources getResources() {
+ if (mResources != null) {
+ return mResources;
+ }
+ if (mOverrideConfiguration == null) {
+ mResources = super.getResources();
+ return mResources;
+ } else {
+ Context resc = createConfigurationContext(mOverrideConfiguration);
+ mResources = resc.getResources();
+ return mResources;
+ }
+ }
@Override public void setTheme(int resid) {
mThemeResource = resid;
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 6e4e82c..63a79e4 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -801,11 +801,13 @@
* #loadDataWithBaseURL(String,String,String,String,String)
* loadDataWithBaseURL()} with an appropriate base URL.
* <p>
- * If the value of the encoding parameter is 'base64', then the data must
- * be encoded as base64. Otherwise, the data must use ASCII encoding for
+ * The encoding parameter specifies whether the data is base64 or URL
+ * encoded. If the data is base64 encoded, the value of the encoding
+ * parameter must be 'base64'. For all other values of the parameter,
+ * including null, it is assumed that the data uses ASCII encoding for
* octets inside the range of safe URL characters and use the standard %xx
- * hex encoding of URLs for octets outside that range. For example,
- * '#', '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
+ * hex encoding of URLs for octets outside that range. For example, '#',
+ * '%', '\', '?' should be replaced by %23, %25, %27, %3f respectively.
* <p>
* The 'data' scheme URL formed by this method uses the default US-ASCII
* charset. If you need need to set a different charset, you should form a
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 7eab72d..e98000a 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -155,7 +155,7 @@
<string name="global_action_lock" msgid="2844945191792119712">"Verrouillage de l\'écran"</string>
<string name="global_action_power_off" msgid="4471879440839879722">"Éteindre"</string>
<string name="global_action_bug_report" msgid="7934010578922304799">"Rapport de bug"</string>
- <string name="bugreport_title" msgid="2667494803742548533">"Établir un rapport de bug"</string>
+ <string name="bugreport_title" msgid="2667494803742548533">"Créer un rapport de bug"</string>
<string name="bugreport_message" msgid="398447048750350456">"Cela permet de recueillir des informations concernant l\'état actuel de votre appareil. Ces informations sont ensuite envoyées sous forme d\'e-mail. Merci de patienter pendant la préparation du rapport de bug. Cette opération peut prendre quelques instants."</string>
<string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Mode silencieux"</string>
<string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Le son est désactivé."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 093c19d..cf8fa01 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1075,7 +1075,7 @@
<string name="usb_storage_error_message" product="nosdcard" msgid="3017045217365540658">"USB विशाल संग्रहण के लिए आपके USB संग्रहण का उपयोग करने में समस्या है."</string>
<string name="usb_storage_error_message" product="default" msgid="2876018512716970313">"USB विशाल संग्रहण के लिए आपके SD कार्ड का उपयोग करने में समस्या है."</string>
<string name="usb_storage_notification_title" msgid="8175892554757216525">"USB कनेक्ट किया गया"</string>
- <string name="usb_storage_notification_message" msgid="939822783828183763">"आपके कंप्यूटर में/से फ़ाइल की प्रतिलिपि बनाने के लिए चयन करें."</string>
+ <string name="usb_storage_notification_message" msgid="939822783828183763">"आपके कंप्यूटर में/से फ़ाइल की प्रतिलिपि बनाने के लिए चुनें."</string>
<string name="usb_storage_stop_notification_title" msgid="2336058396663516017">"USB संग्रहण बंद करें"</string>
<string name="usb_storage_stop_notification_message" msgid="1656852098555623822">"USB संग्रहण बंद करने के लिए स्पर्श करें."</string>
<string name="usb_storage_stop_title" msgid="660129851708775853">"USB संग्रहण उपयोग में है"</string>
diff --git a/docs/html/design/downloads/index.jd b/docs/html/design/downloads/index.jd
index be75800..4503098 100644
--- a/docs/html/design/downloads/index.jd
+++ b/docs/html/design/downloads/index.jd
@@ -12,7 +12,7 @@
<div class="layout-content-col span-4">
<p>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Downloads_20120814.zip">Download All</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Android_Design_Downloads_20120814.zip">Download All</a>
</p>
</div>
@@ -37,10 +37,10 @@
<div class="layout-content-col span-4">
<p>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Fireworks_Stencil_20120814.png">Adobe® Fireworks® PNG Stencil</a>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Illustrator_Vectors_20120814.ai">Adobe® Illustrator® Stencil</a>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_OmniGraffle_Stencil_20120814.graffle">Omni® OmniGraffle® Stencil</a>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Holo_Widgets_20120814.zip">Adobe® Photoshop® Sources</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Android_Design_Fireworks_Stencil_20120814.png">Adobe® Fireworks® PNG Stencil</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Android_Design_Illustrator_Vectors_20120814.ai">Adobe® Illustrator® Stencil</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Android_Design_OmniGraffle_Stencil_20120814.graffle">Omni® OmniGraffle® Stencil</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Android_Design_Holo_Widgets_20120814.zip">Adobe® Photoshop® Sources</a>
</p>
</div>
@@ -66,7 +66,7 @@
<div class="layout-content-col span-4">
<p>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Icons_20120814.zip">Action Bar Icon Pack</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Android_Design_Icons_20120814.zip">Action Bar Icon Pack</a>
</p>
</div>
@@ -91,8 +91,8 @@
<div class="layout-content-col span-4">
<p>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Roboto_Hinted_20111129.zip">Roboto</a>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Roboto_Hinted_20111129.zip">Roboto</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a>
</p>
</div>
@@ -115,7 +115,7 @@
<div class="layout-content-col span-4">
<p>
- <a class="download-button" href="https://dl-ssl.google.com/android/design/Android_Design_Color_Swatches_20120229.zip">Color Swatches</a>
+ <a class="download-button" href="{@docRoot}downloads/design/Android_Design_Color_Swatches_20120229.zip">Color Swatches</a>
</p>
</div>
diff --git a/docs/html/design/patterns/actionbar.jd b/docs/html/design/patterns/actionbar.jd
index 9ceb499..ba5b400 100644
--- a/docs/html/design/patterns/actionbar.jd
+++ b/docs/html/design/patterns/actionbar.jd
@@ -293,7 +293,7 @@
</p>
<p>
-<a href="https://dl-ssl.google.com/android/design/Android_Design_Icons_20120229.zip">Download the Action Bar Icon Pack</a>
+<a href="{@docRoot}downloads/design/Android_Design_Icons_20120229.zip">Download the Action Bar Icon Pack</a>
</p>
diff --git a/docs/html/design/style/color.jd b/docs/html/design/style/color.jd
index 9c7b6b6..5be34ac 100644
--- a/docs/html/design/style/color.jd
+++ b/docs/html/design/style/color.jd
@@ -115,7 +115,7 @@
<p>Blue is the standard accent color in Android's color palette. Each color has a corresponding darker
shade that can be used as a complement when needed.</p>
-<p><a href="https://dl-ssl.google.com/android/design/Android_Design_Color_Swatches_20120229.zip">Download the swatches</a></p>
+<p><a href="{@docRoot}downloads/design/Android_Design_Color_Swatches_20120229.zip">Download the swatches</a></p>
<img src="{@docRoot}design/media/color_spectrum.png">
diff --git a/docs/html/design/style/iconography.jd b/docs/html/design/style/iconography.jd
index 775e45d..31274c5 100644
--- a/docs/html/design/style/iconography.jd
+++ b/docs/html/design/style/iconography.jd
@@ -110,7 +110,7 @@
</p>
<p>
-<a href="https://dl-ssl.google.com/android/design/Android_Design_Icons_20120229.zip">Download the Action Bar Icon Pack</a>
+<a href="{@docRoot}downloads/design/Android_Design_Icons_20120229.zip">Download the Action Bar Icon Pack</a>
</p>
diff --git a/docs/html/design/style/typography.jd b/docs/html/design/style/typography.jd
index db2fb5f..a699bed 100644
--- a/docs/html/design/style/typography.jd
+++ b/docs/html/design/style/typography.jd
@@ -18,8 +18,8 @@
<img src="{@docRoot}design/media/typography_alphas.png">
-<p><a href="https://dl-ssl.google.com/android/design/Roboto_Hinted_20111129.zip">Download Roboto</a></p>
-<p><a href="https://dl-ssl.google.com/android/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a></p>
+<p><a href="{@docRoot}downloads/design/Roboto_Hinted_20111129.zip">Download Roboto</a></p>
+<p><a href="{@docRoot}downloads/design/Roboto_Specimen_Book_20111129.pdf">Specimen Book</a></p>
</div>
</div>
diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd
index a63270a..3fe23f8 100644
--- a/docs/html/guide/topics/media/camera.jd
+++ b/docs/html/guide/topics/media/camera.jd
@@ -617,7 +617,7 @@
// Create our Preview view and set it as the content of our activity.
mPreview = new CameraPreview(this, mCamera);
- FrameLayout preview = (FrameLayout) findViewById(id.camera_preview);
+ FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
preview.addView(mPreview);
}
}
diff --git a/docs/html/guide/topics/ui/controls/radiobutton.jd b/docs/html/guide/topics/ui/controls/radiobutton.jd
index f6f6d49..c96e576 100644
--- a/docs/html/guide/topics/ui/controls/radiobutton.jd
+++ b/docs/html/guide/topics/ui/controls/radiobutton.jd
@@ -72,7 +72,7 @@
<pre>
public void onRadioButtonClicked(View view) {
// Is the button now checked?
- boolean checked = (RadioButton) view).isChecked();
+ boolean checked = ((RadioButton) view).isChecked();
// Check which radio button was clicked
switch(view.getId()) {
diff --git a/docs/html/guide/topics/ui/settings.jd b/docs/html/guide/topics/ui/settings.jd
index fd3b684..33e164b 100644
--- a/docs/html/guide/topics/ui/settings.jd
+++ b/docs/html/guide/topics/ui/settings.jd
@@ -217,7 +217,7 @@
android:dialogTitle="@string/pref_syncConnectionType"
android:entries="@array/pref_syncConnectionTypes_entries"
android:entryValues="@array/pref_syncConnectionTypes_values"
- android:defaultValue="@string/pref_syncConnectionTypes_default" >
+ android:defaultValue="@string/pref_syncConnectionTypes_default" />
</PreferenceScreen>
</pre>
diff --git a/docs/html/training/basics/activity-lifecycle/starting.jd b/docs/html/training/basics/activity-lifecycle/starting.jd
index 1a4bc2d..dd17304 100644
--- a/docs/html/training/basics/activity-lifecycle/starting.jd
+++ b/docs/html/training/basics/activity-lifecycle/starting.jd
@@ -112,7 +112,7 @@
</table>
-->
-<p>As you'll learn in the following lessons, there are several situtations in which an activity
+<p>As you'll learn in the following lessons, there are several situations in which an activity
transitions between different states that are illustrated in figure 1. However, only three of
these states can be static. That is, the activity can exist in one of only three states for an
extended period of time:</p>
diff --git a/docs/html/training/basics/firstapp/starting-activity.jd b/docs/html/training/basics/firstapp/starting-activity.jd
index 4d0a84a..3dafcfa 100644
--- a/docs/html/training/basics/firstapp/starting-activity.jd
+++ b/docs/html/training/basics/firstapp/starting-activity.jd
@@ -285,8 +285,8 @@
<p>The app is now runnable because the {@link android.content.Intent} in the
first activity now resolves to the {@code DisplayMessageActivity} class. If you run the app now,
-clicking the Send button starts the
-second activity, but it doesn't show anything yet.</p>
+clicking the Send button starts the second activity, but it's still using the default
+"Hello world" layout.</p>
<h2 id="ReceiveIntent">Receive the Intent</h2>
diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java
index 2032f67..af8b0c2 100644
--- a/graphics/java/android/renderscript/RenderScript.java
+++ b/graphics/java/android/renderscript/RenderScript.java
@@ -561,6 +561,12 @@
return rsnScriptCCreate(mContext, resName, cacheDir, script, length);
}
+ native int rsnScriptIntrinsicCreate(int con, int id, int eid);
+ synchronized int nScriptIntrinsicCreate(int id, int eid) {
+ validate();
+ return rsnScriptIntrinsicCreate(mContext, id, eid);
+ }
+
native int rsnSamplerCreate(int con, int magFilter, int minFilter,
int wrapS, int wrapT, int wrapR, float aniso);
synchronized int nSamplerCreate(int magFilter, int minFilter,
diff --git a/graphics/java/android/renderscript/ScriptIntrinsic.java b/graphics/java/android/renderscript/ScriptIntrinsic.java
new file mode 100644
index 0000000..6ad1527
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsic.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+
+/**
+ * @hide
+ **/
+public class ScriptIntrinsic extends Script {
+ ScriptIntrinsic(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ public void forEach(Allocation ain, Allocation aout) {
+ forEach(0, ain, aout, null);
+ }
+}
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
new file mode 100644
index 0000000..0ae1449
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicConvolve3x3.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map.Entry;
+import java.util.HashMap;
+
+
+/**
+ * @hide
+ **/
+public class ScriptIntrinsicConvolve3x3 extends ScriptIntrinsic {
+ private float[] mValues = new float[9];
+
+ ScriptIntrinsicConvolve3x3(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+ /**
+ * Supported elements types are float, float4, uchar, uchar4
+ *
+ *
+ * @param rs
+ * @param e
+ *
+ * @return ScriptIntrinsicConvolve3x3
+ */
+ public static ScriptIntrinsicConvolve3x3 create(RenderScript rs, Element e) {
+ int id = rs.nScriptIntrinsicCreate(1, e.getID(rs));
+ return new ScriptIntrinsicConvolve3x3(id, rs);
+
+ }
+
+
+ public void setValues(float v[]) {
+ FieldPacker fp = new FieldPacker(9*4);
+ for (int ct=0; ct < mValues.length; ct++) {
+ mValues[ct] = v[ct];
+ fp.addF32(mValues[ct]);
+ }
+ setVar(0, fp);
+ }
+}
+
diff --git a/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
new file mode 100644
index 0000000..ee5f938
--- /dev/null
+++ b/graphics/java/android/renderscript/ScriptIntrinsicYuvToRGB.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map.Entry;
+import java.util.HashMap;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * @hide
+ **/
+public class ScriptIntrinsicYuvToRGB extends ScriptIntrinsic {
+ ScriptIntrinsicYuvToRGB(int id, RenderScript rs) {
+ super(id, rs);
+ }
+
+
+
+ public static class Builder {
+ RenderScript mRS;
+
+ public Builder(RenderScript rs) {
+ mRS = rs;
+ }
+
+ public void setInputFormat(int inputFormat) {
+
+ }
+
+ public void setOutputFormat(Element e) {
+
+ }
+
+ public ScriptIntrinsicYuvToRGB create() {
+ return null;
+
+ }
+
+ }
+
+}
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 09f6952..a073c1a 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -1071,6 +1071,13 @@
return ret;
}
+static jint
+nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, RsContext con, jint id, jint eid)
+{
+ LOG_API("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", con, id, (void *)eid);
+ return (jint)rsScriptIntrinsicCreate(con, id, (RsElement)eid);
+}
+
// ---------------------------------------------------------------------------
static jint
@@ -1412,6 +1419,7 @@
{"rsnScriptSetVarObj", "(IIII)V", (void*)nScriptSetVarObj },
{"rsnScriptCCreate", "(ILjava/lang/String;Ljava/lang/String;[BI)I", (void*)nScriptCCreate },
+{"rsnScriptIntrinsicCreate", "(III)I", (void*)nScriptIntrinsicCreate },
{"rsnProgramStoreCreate", "(IZZZZZZIII)I", (void*)nProgramStoreCreate },
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 95fc2c5..2de70d462 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -1699,7 +1699,9 @@
addFloat(hOffset);
addFloat(vOffset);
paint->setAntiAlias(true);
- addPaint(paint);
+ SkPaint* addedPaint = addPaint(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
+ fontRenderer.precache(addedPaint, text, count);
return DrawGlInfo::kStatusDone;
}
@@ -1711,7 +1713,9 @@
addInt(count);
addFloats(positions, count * 2);
paint->setAntiAlias(true);
- addPaint(paint);
+ SkPaint* addedPaint = addPaint(paint);
+ FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
+ fontRenderer.precache(addedPaint, text, count);
return DrawGlInfo::kStatusDone;
}
@@ -1742,7 +1746,11 @@
addFloat(x);
addFloat(y);
addFloats(positions, count * 2);
- addPaint(paint);
+ SkPaint* addedPaint = addPaint(paint);
+ if (!reject) {
+ FontRenderer& fontRenderer = mCaches.fontRenderer->getFontRenderer(addedPaint);
+ fontRenderer.precache(addedPaint, text, count);
+ }
addFloat(length);
addSkip(location);
return DrawGlInfo::kStatusDone;
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 60a40c6..c8b3e47 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -770,10 +770,10 @@
addInt((int) pathCopy);
}
- inline void addPaint(SkPaint* paint) {
+ inline SkPaint* addPaint(SkPaint* paint) {
if (!paint) {
addInt((int) NULL);
- return;
+ return paint;
}
SkPaint* paintCopy = mPaintMap.valueFor(paint);
@@ -785,6 +785,8 @@
}
addInt((int) paintCopy);
+
+ return paintCopy;
}
inline void addDisplayList(DisplayList* displayList) {
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index ccddd91..a596fa9 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -37,11 +37,78 @@
#define DEFAULT_TEXT_CACHE_WIDTH 1024
#define DEFAULT_TEXT_CACHE_HEIGHT 256
#define MAX_TEXT_CACHE_WIDTH 2048
-#define TEXTURE_BORDER_SIZE 1
+#define CACHE_BLOCK_ROUNDING_SIZE 4
#define AUTO_KERN(prev, next) (((next) - (prev) + 32) >> 6 << 16)
///////////////////////////////////////////////////////////////////////////////
+// CacheBlock
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Insert new block into existing linked list of blocks. Blocks are sorted in increasing-width
+ * order, except for the final block (the remainder space at the right, since we fill from the
+ * left).
+ */
+CacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock *newBlock) {
+#if DEBUG_FONT_RENDERER
+ ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d",
+ newBlock, newBlock->mX, newBlock->mY,
+ newBlock->mWidth, newBlock->mHeight);
+#endif
+ CacheBlock *currBlock = head;
+ CacheBlock *prevBlock = NULL;
+ while (currBlock && currBlock->mY != TEXTURE_BORDER_SIZE) {
+ if (newBlock->mWidth < currBlock->mWidth) {
+ newBlock->mNext = currBlock;
+ newBlock->mPrev = prevBlock;
+ currBlock->mPrev = newBlock;
+ if (prevBlock) {
+ prevBlock->mNext = newBlock;
+ return head;
+ } else {
+ return newBlock;
+ }
+ }
+ prevBlock = currBlock;
+ currBlock = currBlock->mNext;
+ }
+ // new block larger than all others - insert at end (but before the remainder space, if there)
+ newBlock->mNext = currBlock;
+ newBlock->mPrev = prevBlock;
+ if (currBlock) {
+ currBlock->mPrev = newBlock;
+ }
+ if (prevBlock) {
+ prevBlock->mNext = newBlock;
+ return head;
+ } else {
+ return newBlock;
+ }
+}
+
+CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock *blockToRemove) {
+#if DEBUG_FONT_RENDERER
+ ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d",
+ blockToRemove, blockToRemove->mX, blockToRemove->mY,
+ blockToRemove->mWidth, blockToRemove->mHeight);
+#endif
+ CacheBlock* newHead = head;
+ CacheBlock* nextBlock = blockToRemove->mNext;
+ CacheBlock* prevBlock = blockToRemove->mPrev;
+ if (prevBlock) {
+ prevBlock->mNext = nextBlock;
+ } else {
+ newHead = nextBlock;
+ }
+ if (nextBlock) {
+ nextBlock->mPrev = prevBlock;
+ }
+ delete blockToRemove;
+ return newHead;
+}
+
+///////////////////////////////////////////////////////////////////////////////
// CacheTextureLine
///////////////////////////////////////////////////////////////////////////////
@@ -50,14 +117,73 @@
return false;
}
- if (mCurrentCol + glyph.fWidth + TEXTURE_BORDER_SIZE * 2 < mMaxWidth) {
- *retOriginX = mCurrentCol + TEXTURE_BORDER_SIZE;
- *retOriginY = mCurrentRow + TEXTURE_BORDER_SIZE;
- mCurrentCol += glyph.fWidth + TEXTURE_BORDER_SIZE * 2;
- mDirty = true;
- return true;
+ uint16_t glyphW = glyph.fWidth + TEXTURE_BORDER_SIZE;
+ uint16_t glyphH = glyph.fHeight + TEXTURE_BORDER_SIZE;
+ // roundedUpW equals glyphW to the next multiple of CACHE_BLOCK_ROUNDING_SIZE.
+ // This columns for glyphs that are close but not necessarily exactly the same size. It trades
+ // off the loss of a few pixels for some glyphs against the ability to store more glyphs
+ // of varying sizes in one block.
+ uint16_t roundedUpW =
+ (glyphW + CACHE_BLOCK_ROUNDING_SIZE - 1) & -CACHE_BLOCK_ROUNDING_SIZE;
+ CacheBlock *cacheBlock = mCacheBlocks;
+ while (cacheBlock) {
+ // Store glyph in this block iff: it fits the block's remaining space and:
+ // it's the remainder space (mY == 0) or there's only enough height for this one glyph
+ // or it's within ROUNDING_SIZE of the block width
+ if (roundedUpW <= cacheBlock->mWidth && glyphH <= cacheBlock->mHeight &&
+ (cacheBlock->mY == TEXTURE_BORDER_SIZE ||
+ (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) {
+ if (cacheBlock->mHeight - glyphH < glyphH) {
+ // Only enough space for this glyph - don't bother rounding up the width
+ roundedUpW = glyphW;
+ }
+ *retOriginX = cacheBlock->mX;
+ *retOriginY = mCurrentRow + cacheBlock->mY;
+ // If this is the remainder space, create a new cache block for this column. Otherwise,
+ // adjust the info about this column.
+ if (cacheBlock->mY == TEXTURE_BORDER_SIZE) {
+ uint16_t oldX = cacheBlock->mX;
+ // Adjust remainder space dimensions
+ cacheBlock->mWidth -= roundedUpW;
+ cacheBlock->mX += roundedUpW;
+ if (mMaxHeight - glyphH >= glyphH) {
+ // There's enough height left over to create a new CacheBlock
+ CacheBlock *newBlock = new CacheBlock(oldX, glyphH, roundedUpW,
+ mMaxHeight - glyphH);
+#if DEBUG_FONT_RENDERER
+ ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
+ newBlock, newBlock->mX, newBlock->mY,
+ newBlock->mWidth, newBlock->mHeight);
+#endif
+ mCacheBlocks = CacheBlock::insertBlock(mCacheBlocks, newBlock);
+ }
+ } else {
+ // Insert into current column and adjust column dimensions
+ cacheBlock->mY += glyphH;
+ cacheBlock->mHeight -= glyphH;
+#if DEBUG_FONT_RENDERER
+ ALOGD("fitBitmap: Added to existing block: this, x, y, w, h = %p, %d, %d, %d, %d",
+ cacheBlock, cacheBlock->mX, cacheBlock->mY,
+ cacheBlock->mWidth, cacheBlock->mHeight);
+#endif
+ }
+ if (cacheBlock->mHeight < fmin(glyphH, glyphW)) {
+ // If remaining space in this block is too small to be useful, remove it
+ mCacheBlocks = CacheBlock::removeBlock(mCacheBlocks, cacheBlock);
+ }
+ mDirty = true;
+#if DEBUG_FONT_RENDERER
+ ALOGD("fitBitmap: current block list:");
+ mCacheBlocks->output();
+#endif
+ ++mNumGlyphs;
+ return true;
+ }
+ cacheBlock = cacheBlock->mNext;
}
-
+#if DEBUG_FONT_RENDERER
+ ALOGD("fitBitmap: returning false for glyph of size %d, %d", glyphW, glyphH);
+#endif
return false;
}
@@ -297,6 +423,27 @@
render(paint, text, start, len, numGlyphs, 0, 0, MEASURE, NULL, 0, 0, bounds, positions);
}
+void Font::precache(SkPaint* paint, const char* text, int numGlyphs) {
+
+ if (numGlyphs == 0 || text == NULL) {
+ return;
+ }
+ int glyphsCount = 0;
+
+ while (glyphsCount < numGlyphs) {
+ glyph_t glyph = GET_GLYPH(text);
+
+ // Reached the end of the string
+ if (IS_END_OF_STRING(glyph)) {
+ break;
+ }
+
+ CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph);
+
+ glyphsCount++;
+ }
+}
+
void Font::render(SkPaint* paint, const char* text, uint32_t start, uint32_t len,
int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* positions) {
@@ -545,9 +692,33 @@
mActiveFonts[i]->invalidateTextureCache();
}
+ uint16_t totalGlyphs = 0;
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
- mCacheLines[i]->mCurrentCol = 0;
+ totalGlyphs += mCacheLines[i]->mNumGlyphs;
+ mCacheLines[i]->init();
}
+
+#if DEBUG_FONT_RENDERER
+ ALOGD("FontRenderer: flushAllAndInvalidatel");
+ // Erase caches, just as a debugging facility
+ if (mCacheTextureSmall && mCacheTextureSmall->mTexture) {
+ memset(mCacheTextureSmall->mTexture, 0,
+ mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight);
+ }
+ if (mCacheTexture128 && mCacheTexture128->mTexture) {
+ memset(mCacheTexture128->mTexture, 0,
+ mCacheTexture128->mWidth * mCacheTexture128->mHeight);
+ }
+ if (mCacheTexture256 && mCacheTexture256->mTexture) {
+ memset(mCacheTexture256->mTexture, 0,
+ mCacheTexture256->mWidth * mCacheTexture256->mHeight);
+ }
+ if (mCacheTexture512 && mCacheTexture512->mTexture) {
+ memset(mCacheTexture512->mTexture, 0,
+ mCacheTexture512->mWidth * mCacheTexture512->mHeight);
+ }
+ ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
+#endif
}
void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
@@ -573,7 +744,16 @@
cacheLine->mCacheTexture == mCacheTexture256 ||
cacheLine->mCacheTexture == mCacheTexture512) &&
cacheLine->mCacheTexture->mTexture != NULL) {
- cacheLine->mCurrentCol = 0;
+#if DEBUG_FONT_RENDERER
+ if (cacheLine->mCacheTexture == mCacheTexture128) {
+ ALOGD("flushing cacheTexture128");
+ } else if (cacheLine->mCacheTexture == mCacheTexture256) {
+ ALOGD("flushing cacheTexture256");
+ } else {
+ ALOGD("flushing cacheTexture512");
+ }
+#endif
+ cacheLine->init();
for (uint32_t i = 0; i < mActiveFonts.size(); i++) {
mActiveFonts[i]->invalidateTextureCache(cacheLine);
}
@@ -614,9 +794,12 @@
uint32_t* retOriginX, uint32_t* retOriginY) {
cachedGlyph->mIsValid = false;
// If the glyph is too tall, don't cache it
- if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
- ALOGE("Font size to large to fit in cache. width, height = %i, %i",
- (int) glyph.fWidth, (int) glyph.fHeight);
+ if (mCacheLines.size() == 0 ||
+ glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
+ if (mCacheLines.size() != 0) {
+ ALOGE("Font size too large to fit in cache. width, height = %i, %i",
+ (int) glyph.fWidth, (int) glyph.fHeight);
+ }
return;
}
@@ -747,26 +930,26 @@
mUploadTexture = false;
// Split up our default cache texture into lines of certain widths
int nextLine = 0;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 18, nextLine, 0, mCacheTextureSmall));
+ mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 18, nextLine, mCacheTextureSmall));
nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, 0, mCacheTextureSmall));
+ mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, mCacheTextureSmall));
nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, 0, mCacheTextureSmall));
+ mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, mCacheTextureSmall));
nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, 0, mCacheTextureSmall));
+ mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, mCacheTextureSmall));
nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, 0, mCacheTextureSmall));
+ mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, mCacheTextureSmall));
nextLine += mCacheLines.top()->mMaxHeight;
- mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 42, nextLine, 0, mCacheTextureSmall));
+ mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 42, nextLine, mCacheTextureSmall));
nextLine += mCacheLines.top()->mMaxHeight;
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, mSmallCacheHeight - nextLine,
- nextLine, 0, mCacheTextureSmall));
+ nextLine, mCacheTextureSmall));
// The first cache is split into 2 lines of height 128, the rest have just one cache line.
- mCacheLines.push(new CacheTextureLine(maxWidth, 128, 0, 0, mCacheTexture128));
- mCacheLines.push(new CacheTextureLine(maxWidth, 128, 128, 0, mCacheTexture128));
- mCacheLines.push(new CacheTextureLine(maxWidth, 256, 0, 0, mCacheTexture256));
- mCacheLines.push(new CacheTextureLine(maxWidth, 512, 0, 0, mCacheTexture512));
+ mCacheLines.push(new CacheTextureLine(maxWidth, 128, 0, mCacheTexture128));
+ mCacheLines.push(new CacheTextureLine(maxWidth, 128, 128, mCacheTexture128));
+ mCacheLines.push(new CacheTextureLine(maxWidth, 256, 0, mCacheTexture256));
+ mCacheLines.push(new CacheTextureLine(maxWidth, 512, 0, mCacheTexture512));
}
// Avoid having to reallocate memory and render quad by quad
@@ -837,6 +1020,10 @@
glBindTexture(GL_TEXTURE_2D, cacheTexture->mTextureId);
lastTextureId = cacheTexture->mTextureId;
}
+#if DEBUG_FONT_RENDERER
+ ALOGD("glTextSubimage for cacheLine %d: xOff, yOff, width height = %d, %d, %d, %d", i,
+ xOffset, yOffset, width, height);
+#endif
glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height,
GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
@@ -960,43 +1147,7 @@
}
}
-uint32_t FontRenderer::getRemainingCacheCapacity() {
- uint32_t remainingCapacity = 0;
- float totalPixels = 0;
-
- //avoid divide by zero if the size is 0
- if (mCacheLines.size() == 0) {
- return 0;
- }
- for(uint32_t i = 0; i < mCacheLines.size(); i ++) {
- remainingCapacity += (mCacheLines[i]->mMaxWidth - mCacheLines[i]->mCurrentCol);
- totalPixels += mCacheLines[i]->mMaxWidth;
- }
- remainingCapacity = (remainingCapacity * 100) / totalPixels;
- return remainingCapacity;
-}
-
-void FontRenderer::precacheLatin(SkPaint* paint) {
- // Remaining capacity is measured in %
- uint32_t remainingCapacity = getRemainingCacheCapacity();
- uint32_t precacheIndex = 0;
-
- // We store a string with letters in a rough frequency of occurrence
- String16 l("eisarntolcdugpmhbyfvkwzxjq EISARNTOLCDUGPMHBYFVKWZXJQ,.?!()-+@;:'0123456789");
-
- size_t size = l.size();
- uint16_t latin[size];
- paint->utfToGlyphs(l.string(), SkPaint::kUTF16_TextEncoding, size * sizeof(char16_t), latin);
-
- while (remainingCapacity > 25 && precacheIndex < size) {
- mCurrentFont->getCachedGlyph(paint, TO_GLYPH(latin[precacheIndex]));
- remainingCapacity = getRemainingCacheCapacity();
- precacheIndex++;
- }
-}
-
void FontRenderer::setFont(SkPaint* paint, uint32_t fontId, float fontSize) {
- uint32_t currentNumFonts = mActiveFonts.size();
int flags = 0;
if (paint->isFakeBoldText()) {
flags |= Font::kFakeBold;
@@ -1012,12 +1163,6 @@
mCurrentFont = Font::create(this, fontId, fontSize, flags, italicStyle,
scaleX, style, strokeWidth);
- const float maxPrecacheFontSize = 40.0f;
- bool isNewFont = currentNumFonts != mActiveFonts.size();
-
- if (isNewFont && fontSize <= maxPrecacheFontSize) {
- precacheLatin(paint);
- }
}
FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const char *text,
@@ -1084,6 +1229,25 @@
}
}
+void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs) {
+ int flags = 0;
+ if (paint->isFakeBoldText()) {
+ flags |= Font::kFakeBold;
+ }
+ const float skewX = paint->getTextSkewX();
+ uint32_t italicStyle = *(uint32_t*) &skewX;
+ const float scaleXFloat = paint->getTextScaleX();
+ uint32_t scaleX = *(uint32_t*) &scaleXFloat;
+ SkPaint::Style style = paint->getStyle();
+ const float strokeWidthFloat = paint->getStrokeWidth();
+ uint32_t strokeWidth = *(uint32_t*) &strokeWidthFloat;
+ float fontSize = paint->getTextSize();
+ Font* font = Font::create(this, SkTypeface::UniqueID(paint->getTypeface()),
+ fontSize, flags, italicStyle, scaleX, style, strokeWidth);
+
+ font->precache(paint, text, numGlyphs);
+}
+
bool FontRenderer::renderText(SkPaint* paint, const Rect* clip, const char *text,
uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, Rect* bounds) {
if (!mCurrentFont) {
diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h
index 9ed6932..8b1d10c8 100644
--- a/libs/hwui/FontRenderer.h
+++ b/libs/hwui/FontRenderer.h
@@ -53,6 +53,8 @@
#define IS_END_OF_STRING(glyph) glyph < 0
#endif
+#define TEXTURE_BORDER_SIZE 1
+
///////////////////////////////////////////////////////////////////////////////
// Declarations
///////////////////////////////////////////////////////////////////////////////
@@ -80,16 +82,79 @@
bool mLinearFiltering;
};
+/**
+ * CacheBlock is a noce in a linked list of current free space areas in a CacheTextureLine.
+ * Using CacheBlocks enables us to pack the cache line from top to bottom as well as left to right.
+ * When we add a glyph to the cache, we see if it fits within one of the existing columns that
+ * have already been started (this is the case if the glyph fits vertically as well as
+ * horizontally, and if its width is sufficiently close to the column width to avoid
+ * sub-optimal packing of small glyphs into wide columns). If there is no column in which the
+ * glyph fits, we check the final node, which is the remaining space in the cache line, creating
+ * a new column as appropriate.
+ *
+ * As columns fill up, we remove their CacheBlock from the list to avoid having to check
+ * small blocks in the future.
+ */
+struct CacheBlock {
+ uint16_t mX;
+ uint16_t mY;
+ uint16_t mWidth;
+ uint16_t mHeight;
+ CacheBlock* mNext;
+ CacheBlock* mPrev;
+
+ CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height, bool empty = false):
+ mX(x), mY(y), mWidth(width), mHeight(height), mNext(NULL), mPrev(NULL)
+ {
+ }
+
+ static CacheBlock* insertBlock(CacheBlock* head, CacheBlock *newBlock);
+
+ static CacheBlock* removeBlock(CacheBlock* head, CacheBlock *blockToRemove);
+
+ void output() {
+ CacheBlock *currBlock = this;
+ while (currBlock) {
+ ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d",
+ currBlock, currBlock->mX, currBlock->mY, currBlock->mWidth, currBlock->mHeight);
+ currBlock = currBlock->mNext;
+ }
+ }
+};
+
class CacheTextureLine {
public:
CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
- uint32_t currentCol, CacheTexture* cacheTexture):
+ CacheTexture* cacheTexture):
mMaxHeight(maxHeight),
mMaxWidth(maxWidth),
mCurrentRow(currentRow),
- mCurrentCol(currentCol),
mDirty(false),
+ mNumGlyphs(0),
mCacheTexture(cacheTexture) {
+ mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
+ maxWidth - TEXTURE_BORDER_SIZE, maxHeight - TEXTURE_BORDER_SIZE, true);
+ }
+
+ ~CacheTextureLine() {
+ reset();
+ }
+
+ void reset() {
+ // Delete existing cache blocks
+ while (mCacheBlocks != NULL) {
+ CacheBlock* tmpBlock = mCacheBlocks;
+ mCacheBlocks = mCacheBlocks->mNext;
+ delete tmpBlock;
+ }
+ mNumGlyphs = 0;
+ }
+
+ void init() {
+ // reset, then create a new remainder space to start again
+ reset();
+ mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
+ mMaxWidth - TEXTURE_BORDER_SIZE, mMaxHeight - TEXTURE_BORDER_SIZE, true);
}
bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
@@ -97,9 +162,10 @@
uint16_t mMaxHeight;
uint16_t mMaxWidth;
uint32_t mCurrentRow;
- uint32_t mCurrentCol;
bool mDirty;
+ uint16_t mNumGlyphs;
CacheTexture* mCacheTexture;
+ CacheBlock* mCacheBlocks;
};
struct CachedGlyphInfo {
@@ -179,6 +245,8 @@
MEASURE,
};
+ void precache(SkPaint* paint, const char* text, int numGlyphs);
+
void render(SkPaint* paint, const char *text, uint32_t start, uint32_t len,
int numGlyphs, int x, int y, RenderMode mode, uint8_t *bitmap,
uint32_t bitmapW, uint32_t bitmapH, Rect *bounds, const float* positions);
@@ -244,6 +312,9 @@
}
void setFont(SkPaint* paint, uint32_t fontId, float fontSize);
+
+ void precache(SkPaint* paint, const char* text, int numGlyphs);
+
// bounds is an out parameter
bool renderText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex,
uint32_t len, int numGlyphs, int x, int y, Rect* bounds);
@@ -327,8 +398,6 @@
void initRender(const Rect* clip, Rect* bounds);
void finishRender();
- void precacheLatin(SkPaint* paint);
-
void issueDrawCommand();
void appendMeshQuadNoClip(float x1, float y1, float u1, float v1,
float x2, float y2, float u2, float v2,
@@ -347,7 +416,6 @@
uint32_t mSmallCacheHeight;
Vector<CacheTextureLine*> mCacheLines;
- uint32_t getRemainingCacheCapacity();
Font* mCurrentFont;
Vector<Font*> mActiveFonts;
diff --git a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml b/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
index c478334..47c511c 100644
--- a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
+++ b/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
@@ -31,10 +31,16 @@
android:layout_height="@*android:dimen/status_bar_height"
/>
- <include layout="@layout/status_bar_expanded"
- android:layout_width="@dimen/notification_panel_width"
- android:layout_height="0dp"
- android:layout_gravity="center_horizontal|top"
- />
+ <com.android.systemui.statusbar.phone.PanelHolder
+ android:id="@+id/panel_holder"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <include layout="@layout/status_bar_expanded"
+ android:layout_width="@dimen/notification_panel_width"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|top"
+ />
+ </com.android.systemui.statusbar.phone.PanelHolder>
</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 5841978..828dba4 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -18,12 +18,12 @@
*/
-->
-<FrameLayout
+<com.android.systemui.statusbar.phone.NotificationPanelView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
android:id="@+id/notification_panel"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_width="0dp"
+ android:layout_height="0dp"
android:background="@drawable/notification_panel_bg"
android:paddingTop="@dimen/notification_panel_padding_top"
android:layout_marginLeft="@dimen/notification_panel_margin_left"
@@ -42,7 +42,7 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/close_handle_underlap"
android:orientation="vertical"
>
@@ -65,7 +65,7 @@
<ScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_height="wrap_content"
android:fadingEdge="none"
android:overScrollMode="always"
>
@@ -78,7 +78,7 @@
</ScrollView>
</LinearLayout>
- <com.android.systemui.statusbar.phone.CloseDragHandle android:id="@+id/close"
+ <LinearLayout android:id="@+id/handle"
android:layout_width="match_parent"
android:layout_height="@dimen/close_handle_height"
android:layout_gravity="bottom"
@@ -91,6 +91,5 @@
android:scaleType="fitXY"
android:src="@drawable/status_bar_close"
/>
-
- </com.android.systemui.statusbar.phone.CloseDragHandle>
-</FrameLayout><!-- end of sliding panel -->
+ </LinearLayout>
+</com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 5bf1a58..ad905bd 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -32,9 +32,15 @@
android:layout_height="@*android:dimen/status_bar_height"
/>
- <include layout="@layout/status_bar_expanded"
+ <com.android.systemui.statusbar.phone.PanelHolder
+ android:id="@+id/panel_holder"
android:layout_width="match_parent"
- android:layout_height="0dp"
- />
+ android:layout_height="match_parent"
+ >
+ <include layout="@layout/status_bar_expanded"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ />
+ </com.android.systemui.statusbar.phone.PanelHolder>
</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 9bbfc91..19b64ba 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -33,4 +33,5 @@
<drawable name="system_bar_background">#ff000000</drawable>
<!-- the darkening filter applied to notifications -->
<drawable name="notification_icon_area_smoke">#aa000000</drawable>
+ <color name="notification_panel_scrim_color">#B0000000</color>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
index 475fb6d..b36e71a 100644
--- a/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/SearchPanelView.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
+import android.os.UserId;
import android.os.Vibrator;
import android.provider.Settings;
import android.util.AttributeSet;
@@ -73,14 +74,15 @@
// Close Recent Apps if needed
mBar.animateCollapse(CommandQueue.FLAG_EXCLUDE_SEARCH_PANEL);
// Launch Assist
- Intent intent = SearchManager.getAssistIntent(mContext);
+ Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, UserId.USER_CURRENT);
if (intent == null) return;
try {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.search_launch_enter, R.anim.search_launch_exit,
getHandler(), this);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent, opts.toBundle());
+ mContext.startActivityAsUser(intent, opts.toBundle(), UserId.USER_CURRENT);
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "Activity not found for " + intent.getAction());
onAnimationStarted();
@@ -140,7 +142,8 @@
}
private void maybeSwapSearchIcon() {
- Intent intent = SearchManager.getAssistIntent(mContext);
+ Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, UserId.USER_CURRENT);
if (intent != null) {
ComponentName component = intent.getComponent();
if (component == null || !mGlowPadView.replaceTargetDrawablesIfPresent(component,
@@ -277,6 +280,7 @@
}
public boolean isAssistantAvailable() {
- return SearchManager.getAssistIntent(mContext) != null;
+ return ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, UserId.USER_CURRENT) != null;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
new file mode 100644
index 0000000..ae7fb27
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+
+public class NotificationPanelView extends PanelView {
+ public NotificationPanelView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ android.util.Slog.v("NotificationPanelView", "ctor");
+ }
+
+
+ @Override
+ public void fling(float vel, boolean always) {
+ ((PhoneStatusBarView) mBar).mBar.getGestureRecorder().tag(
+ "fling " + ((vel > 0) ? "open" : "closed"),
+ "v=" + vel);
+ super.fling(vel, always);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
new file mode 100644
index 0000000..b2c72e8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -0,0 +1,115 @@
+package com.android.systemui.statusbar.phone;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Slog;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+public class PanelBar extends FrameLayout {
+ public static final boolean DEBUG = true;
+ public static final String TAG = PanelView.class.getSimpleName();
+ public static final void LOG(String fmt, Object... args) {
+ if (!DEBUG) return;
+ Slog.v(TAG, String.format(fmt, args));
+ }
+
+ private PanelHolder mPanelHolder;
+ private ArrayList<PanelView> mPanels = new ArrayList<PanelView>();
+ private PanelView mTouchingPanel;
+
+ public PanelBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ }
+
+ public void addPanel(PanelView pv) {
+ mPanels.add(pv);
+ pv.setBar(this);
+ }
+
+ public void setPanelHolder(PanelHolder ph) {
+ if (ph == null) {
+ Slog.e(TAG, "setPanelHolder: null PanelHolder", new Throwable());
+ return;
+ }
+ ph.setBar(this);
+ mPanelHolder = ph;
+ final int N = ph.getChildCount();
+ for (int i=0; i<N; i++) {
+ final PanelView v = (PanelView) ph.getChildAt(i);
+ if (v != null) {
+ addPanel(v);
+ }
+ }
+ }
+
+ public float getBarHeight() {
+ return getMeasuredHeight();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // figure out which panel needs to be talked to here
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ final int N = mPanels.size();
+ final int i = (int)(N * event.getX() / getMeasuredWidth());
+ mTouchingPanel = mPanels.get(i);
+ mPanelHolder.setSelectedPanel(mTouchingPanel);
+ LOG("PanelBar.onTouch: ACTION_DOWN: panel %d", i);
+ onPanelPeeked();
+ }
+ final boolean result = mTouchingPanel.getHandle().dispatchTouchEvent(event);
+ return result;
+ }
+
+ public void panelExpansionChanged(PanelView panel, float frac) {
+ boolean fullyClosed = true;
+ boolean fullyOpened = false;
+ for (PanelView pv : mPanels) {
+ if (pv.getExpandedHeight() > 0f) {
+ fullyClosed = false;
+ final float thisFrac = pv.getExpandedFraction();
+ LOG("panel %s: f=%.1f", pv, thisFrac);
+ if (panel == pv) {
+ if (thisFrac == 1f) fullyOpened = true;
+ } else {
+ pv.setExpandedFraction(1f-frac);
+ }
+ }
+ }
+ if (fullyOpened) onPanelFullyOpened();
+ if (fullyClosed) onAllPanelsCollapsed();
+ else onPanelPeeked();
+
+ LOG("panelExpansionChanged: [%s%s ]", fullyOpened?" fullyOpened":"", fullyClosed?" fullyClosed":"");
+ }
+
+ public void collapseAllPanels(boolean animate) {
+ for (PanelView pv : mPanels) {
+ if (animate && pv == mTouchingPanel) {
+ mTouchingPanel.collapse();
+ } else {
+ pv.setExpandedFraction(0); // just in case
+ }
+ }
+ }
+
+ public void onPanelPeeked() {
+ LOG("onPanelPeeked");
+ }
+
+ public void onAllPanelsCollapsed() {
+ LOG("onAllPanelsCollapsed");
+ }
+
+ public void onPanelFullyOpened() {
+ LOG("onPanelFullyOpened");
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java
new file mode 100644
index 0000000..abd82bd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelHolder.java
@@ -0,0 +1,65 @@
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.FrameLayout;
+
+public class PanelHolder extends FrameLayout {
+
+ private int mSelectedPanelIndex;
+ private PanelBar mBar;
+
+ public PanelHolder(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setChildrenDrawingOrderEnabled(true);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ setChildrenDrawingOrderEnabled(true);
+ }
+
+ public int getPanelIndex(PanelView pv) {
+ final int N = getChildCount();
+ for (int i=0; i<N; i++) {
+ final PanelView v = (PanelView) getChildAt(i);
+ if (pv == v) return i;
+ }
+ return -1;
+ }
+
+ public void setSelectedPanel(PanelView pv) {
+ mSelectedPanelIndex = getPanelIndex(pv);
+ }
+
+ @Override
+ protected int getChildDrawingOrder(int childCount, int i) {
+ if (mSelectedPanelIndex == -1) {
+ return i;
+ } else {
+ if (i == childCount - 1) {
+ return mSelectedPanelIndex;
+ } else if (i >= mSelectedPanelIndex) {
+ return i + 1;
+ } else {
+ return i;
+ }
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mBar.collapseAllPanels(true);
+ break;
+ }
+ return false;
+ }
+
+ public void setBar(PanelBar panelBar) {
+ mBar = panelBar;
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
new file mode 100644
index 0000000..7dc8f7c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -0,0 +1,327 @@
+package com.android.systemui.statusbar.phone;
+
+import android.animation.TimeAnimator;
+import android.animation.TimeAnimator.TimeListener;
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+public class PanelView extends FrameLayout {
+ public static final boolean DEBUG = true;
+ public static final String TAG = PanelView.class.getSimpleName();
+ public static final void LOG(String fmt, Object... args) {
+ if (!DEBUG) return;
+ Log.v(TAG, String.format(fmt, args));
+ }
+
+ public static final boolean BRAKES = false;
+
+ private float mSelfExpandVelocityPx; // classic value: 2000px/s
+ private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
+ private float mFlingExpandMinVelocityPx; // classic value: 200px/s
+ private float mFlingCollapseMinVelocityPx; // classic value: 200px/s
+ private float mCollapseMinDisplayFraction; // classic value: 0.08 (25px/min(320px,480px) on G1)
+ private float mExpandMinDisplayFraction; // classic value: 0.5 (drag open halfway to expand)
+ private float mFlingGestureMaxXVelocityPx; // classic value: 150px/s
+
+ private float mExpandAccelPx; // classic value: 2000px/s/s
+ private float mCollapseAccelPx; // classic value: 2000px/s/s (will be negated to collapse "up")
+
+ private float mFlingGestureMaxOutputVelocityPx; // how fast can it really go? (should be a little
+ // faster than mSelfCollapseVelocityPx)
+
+ private float mCollapseBrakingDistancePx = 200; // XXX Resource
+ private float mExpandBrakingDistancePx = 150; // XXX Resource
+ private float mBrakingSpeedPx = 150; // XXX Resource
+
+ private View mHandleView;
+ private float mTouchOffset;
+ private float mExpandedFraction = 0;
+ private float mExpandedHeight = 0;
+
+ private TimeAnimator mTimeAnimator;
+ private VelocityTracker mVelocityTracker;
+
+ private int[] mAbsPos = new int[2];
+ PanelBar mBar;
+
+ private final TimeListener mAnimationCallback = new TimeListener() {
+ @Override
+ public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
+ animationTick(deltaTime);
+ }
+ };
+
+ private float mVel, mAccel;
+ private int mFullHeight = 0;
+
+ private void animationTick(long dtms) {
+ if (!mTimeAnimator.isStarted()) {
+ // XXX HAX to work around bug in TimeAnimator.end() not resetting its last time
+ mTimeAnimator = new TimeAnimator();
+ mTimeAnimator.setTimeListener(mAnimationCallback);
+
+ mTimeAnimator.start();
+ } else {
+ final float dt = dtms * 0.001f; // ms -> s
+ LOG("tick: v=%.2fpx/s dt=%.4fs", mVel, dt);
+ LOG("tick: before: h=%d", (int) mExpandedHeight);
+
+ final float fh = getFullHeight();
+ final boolean closing = mExpandedHeight > 0 && mVel < 0;
+ boolean braking = false;
+ if (BRAKES) {
+ if (closing) {
+ braking = mExpandedHeight <= mCollapseBrakingDistancePx;
+ mAccel = braking ? 10*mCollapseAccelPx : -mCollapseAccelPx;
+ } else {
+ braking = mExpandedHeight >= (fh-mExpandBrakingDistancePx);
+ mAccel = braking ? 10*-mExpandAccelPx : mExpandAccelPx;
+ }
+ } else {
+ mAccel = closing ? -mCollapseAccelPx : mExpandAccelPx;
+ }
+
+ mVel += mAccel * dt;
+
+ if (braking) {
+ if (closing && mVel > -mBrakingSpeedPx) {
+ mVel = -mBrakingSpeedPx;
+ } else if (!closing && mVel < mBrakingSpeedPx) {
+ mVel = mBrakingSpeedPx;
+ }
+ } else {
+ if (closing && mVel > -mFlingCollapseMinVelocityPx) {
+ mVel = -mFlingCollapseMinVelocityPx;
+ } else if (!closing && mVel > mFlingGestureMaxOutputVelocityPx) {
+ mVel = mFlingGestureMaxOutputVelocityPx;
+ }
+ }
+
+ float h = mExpandedHeight + mVel * dt;
+
+ LOG("tick: new h=%d closing=%s", (int) h, closing?"true":"false");
+
+ setExpandedHeightInternal(h);
+
+ mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+
+ if (mVel == 0
+ || (closing && mExpandedHeight == 0)
+ || (!closing && mExpandedHeight == getFullHeight())) {
+ mTimeAnimator.end();
+ }
+ }
+ }
+
+ public PanelView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mTimeAnimator = new TimeAnimator();
+ mTimeAnimator.setTimeListener(mAnimationCallback);
+ }
+
+ private void loadDimens() {
+ final Resources res = getContext().getResources();
+
+ mSelfExpandVelocityPx = res.getDimension(R.dimen.self_expand_velocity);
+ mSelfCollapseVelocityPx = res.getDimension(R.dimen.self_collapse_velocity);
+ mFlingExpandMinVelocityPx = res.getDimension(R.dimen.fling_expand_min_velocity);
+ mFlingCollapseMinVelocityPx = res.getDimension(R.dimen.fling_collapse_min_velocity);
+
+ mCollapseMinDisplayFraction = res.getFraction(R.dimen.collapse_min_display_fraction, 1, 1);
+ mExpandMinDisplayFraction = res.getFraction(R.dimen.expand_min_display_fraction, 1, 1);
+
+ mExpandAccelPx = res.getDimension(R.dimen.expand_accel);
+ mCollapseAccelPx = res.getDimension(R.dimen.collapse_accel);
+
+ mFlingGestureMaxXVelocityPx = res.getDimension(R.dimen.fling_gesture_max_x_velocity);
+
+ mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
+ }
+
+ private void trackMovement(MotionEvent event) {
+ // Add movement to velocity tracker using raw screen X and Y coordinates instead
+ // of window coordinates because the window frame may be moving at the same time.
+ float deltaX = event.getRawX() - event.getX();
+ float deltaY = event.getRawY() - event.getY();
+ event.offsetLocation(deltaX, deltaY);
+ mVelocityTracker.addMovement(event);
+ event.offsetLocation(-deltaX, -deltaY);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ loadDimens();
+
+ mHandleView = findViewById(R.id.handle);
+ LOG("handle view: " + mHandleView);
+ if (mHandleView != null) {
+ mHandleView.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ final float y = event.getY();
+ final float rawY = event.getRawY();
+ LOG("handle.onTouch: y=%.1f rawY=%.1f off=%.1f", y, rawY, mTouchOffset);
+ PanelView.this.getLocationOnScreen(mAbsPos);
+
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mVelocityTracker = VelocityTracker.obtain();
+ trackMovement(event);
+ mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight();
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ PanelView.this.setExpandedHeight(rawY - mAbsPos[1] - mTouchOffset);
+
+ mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+
+ trackMovement(event);
+ break;
+
+ case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_CANCEL:
+ trackMovement(event);
+ mVelocityTracker.computeCurrentVelocity(1000);
+
+ float yVel = mVelocityTracker.getYVelocity();
+ boolean negative = yVel < 0;
+
+ float xVel = mVelocityTracker.getXVelocity();
+ if (xVel < 0) {
+ xVel = -xVel;
+ }
+ if (xVel > mFlingGestureMaxXVelocityPx) {
+ xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
+ }
+
+ float vel = (float)Math.hypot(yVel, xVel);
+ if (vel > mFlingGestureMaxOutputVelocityPx) {
+ vel = mFlingGestureMaxOutputVelocityPx;
+ }
+ if (negative) {
+ vel = -vel;
+ }
+
+ LOG("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
+ mVelocityTracker.getXVelocity(),
+ mVelocityTracker.getYVelocity(),
+ xVel, yVel,
+ vel);
+
+ fling(vel, false);
+
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+
+ break;
+ }
+ return true;
+ }});
+ }
+ }
+
+ public void fling(float vel, boolean always) {
+ mVel = vel;
+
+ if (mVel != 0) {
+ animationTick(0); // begin the animation
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ }
+
+ @Override
+ protected void onViewAdded(View child) {
+ LOG("onViewAdded: " + child);
+ }
+
+ public View getHandle() {
+ return mHandleView;
+ }
+
+ // Rubberbands the panel to hold its contents.
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ LOG("onMeasure(%d, %d) -> (%d, %d)",
+ widthMeasureSpec, heightMeasureSpec, getMeasuredWidth(), getMeasuredHeight());
+ mFullHeight = getMeasuredHeight();
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ (int) mExpandedHeight, MeasureSpec.AT_MOST); // MeasureSpec.getMode(heightMeasureSpec));
+ setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
+ }
+
+
+ public void setExpandedHeight(float height) {
+ mTimeAnimator.end();
+ setExpandedHeightInternal(height);
+ }
+
+ public void setExpandedHeightInternal(float h) {
+ float fh = getFullHeight();
+ if (fh == 0) {
+ // Hmm, full height hasn't been computed yet
+ }
+
+ LOG("setExpansion: height=%.1f fh=%.1f", h, fh);
+
+ if (h < 0) h = 0;
+ else if (h > fh) h = fh;
+
+ mExpandedHeight = h;
+
+ requestLayout();
+// FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+// lp.height = (int) mExpandedHeight;
+// setLayoutParams(lp);
+
+ mExpandedFraction = Math.min(1f, h / fh);
+ }
+
+ private float getFullHeight() {
+ return mFullHeight;
+ }
+
+ public void setExpandedFraction(float frac) {
+ setExpandedHeight(getFullHeight() * frac);
+ }
+
+ public float getExpandedHeight() {
+ return mExpandedHeight;
+ }
+
+ public float getExpandedFraction() {
+ return mExpandedFraction;
+ }
+
+ public void setBar(PanelBar panelBar) {
+ mBar = panelBar;
+ }
+
+ public void collapse() {
+ // TODO: abort animation or ongoing touch
+ if (mExpandedHeight > 0) {
+ fling(-mSelfCollapseVelocityPx, /*always=*/ true);
+ }
+ }
+
+ public void expand() {
+ if (mExpandedHeight < getFullHeight()) {
+ fling (mSelfExpandVelocityPx, /*always=*/ true);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 0ccc415..0f84c2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -52,7 +52,6 @@
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
-import android.view.Choreographer;
import android.view.Display;
import android.view.Gravity;
import android.view.IWindowManager;
@@ -77,7 +76,6 @@
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.statusbar.StatusBarNotification;
import com.android.systemui.R;
-import com.android.systemui.UniverseBackground;
import com.android.systemui.recent.RecentTasksLoader;
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.CommandQueue;
@@ -111,7 +109,6 @@
public static final String ACTION_STATUSBAR_START
= "com.android.internal.policy.statusbar.START";
- private static final boolean DIM_BEHIND_EXPANDED_PANEL = true;
private static final boolean SHOW_CARRIER_LABEL = true;
private static final int MSG_OPEN_NOTIFICATION_PANEL = 1000;
@@ -159,8 +156,6 @@
StatusBarWindowView mStatusBarWindow;
PhoneStatusBarView mStatusBarView;
- UniverseBackground mUniverseBackground;
-
int mPixelFormat;
Object mQueueLock = new Object();
@@ -171,7 +166,7 @@
LinearLayout mStatusIcons;
// expanded notifications
- View mNotificationPanel; // the sliding/resizing panel within the notification window
+ PanelView mNotificationPanel; // the sliding/resizing panel within the notification window
ScrollView mScrollView;
View mExpandedContents;
int mNotificationPanelMarginBottomPx, mNotificationPanelMarginLeftPx;
@@ -191,13 +186,8 @@
private int mCarrierLabelHeight;
private TextView mEmergencyCallLabel;
- // drag bar
- CloseDragHandle mCloseView;
- private int mCloseViewHeight;
-
// position
int[] mPositionTmp = new int[2];
- boolean mExpanded;
boolean mExpandedVisible;
// the date view
@@ -222,7 +212,6 @@
boolean mTracking;
VelocityTracker mVelocityTracker;
- Choreographer mChoreographer;
boolean mAnimating;
boolean mClosing; // only valid when mAnimating; indicates the initial acceleration
float mAnimY;
@@ -262,40 +251,6 @@
}
};
- private final Runnable mStartRevealAnimation = new Runnable() {
- @Override
- public void run() {
- mAnimAccel = mExpandAccelPx;
- mAnimVel = mFlingExpandMinVelocityPx;
- mAnimY = getStatusBarHeight();
- updateExpandedViewPos((int)mAnimY);
-
- mAnimating = true;
- mAnimatingReveal = true;
- resetLastAnimTime();
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
- mRevealAnimationCallback, null);
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
- mRevealAnimationCallback, null);
- }
- };
-
- private final Runnable mPerformSelfExpandFling = new Runnable() {
- @Override
- public void run() {
- performFling(0, mSelfExpandVelocityPx, true);
- }
- };
-
- private final Runnable mPerformFling = new Runnable() {
- @Override
- public void run() {
- performFling(mFlingY + mViewDelta, mFlingVelocity, false);
- }
- };
-
@Override
public void start() {
mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
@@ -313,11 +268,6 @@
if (ENABLE_INTRUDERS) addIntruderView();
- mUniverseBackground = new UniverseBackground(mContext);
- mUniverseBackground.setVisibility(View.GONE);
- WindowManagerImpl.getDefault().addView(mUniverseBackground,
- mUniverseBackground.getLayoutParams(mDisplay));
-
// Lastly, call to the icon policy to install/update all the icons.
mIconPolicy = new PhoneStatusBarPolicy(mContext);
}
@@ -345,7 +295,7 @@
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (mExpanded && !mAnimating) {
+ if (mExpandedVisible && !mAnimating) {
animateCollapse();
}
}
@@ -353,7 +303,12 @@
}});
mStatusBarView = (PhoneStatusBarView) mStatusBarWindow.findViewById(R.id.status_bar);
- mNotificationPanel = mStatusBarWindow.findViewById(R.id.notification_panel);
+ mStatusBarView.setBar(this);
+
+ PanelHolder holder = (PanelHolder) mStatusBarWindow.findViewById(R.id.panel_holder);
+ mStatusBarView.setPanelHolder(holder);
+
+ mNotificationPanel = (PanelView) mStatusBarWindow.findViewById(R.id.notification_panel);
// don't allow clicks on the panel to pass through to the background where they will cause the panel to close
mNotificationPanel.setOnTouchListener(new View.OnTouchListener() {
@Override
@@ -380,10 +335,6 @@
updateShowSearchHoldoff();
- mStatusBarView.mService = this;
-
- mChoreographer = Choreographer.getInstance();
-
try {
boolean showNav = mWindowManager.hasNavigationBar();
if (DEBUG) Slog.v(TAG, "hasNavigationBar=" + showNav);
@@ -429,10 +380,6 @@
TickerView tickerView = (TickerView)mStatusBarView.findViewById(R.id.tickerText);
tickerView.mTicker = mTicker;
- mCloseView = (CloseDragHandle)mStatusBarWindow.findViewById(R.id.close);
- mCloseView.mService = this;
- mCloseViewHeight = res.getDimensionPixelSize(R.dimen.close_handle_height);
-
mEdgeBorder = res.getDimensionPixelSize(R.dimen.status_bar_edge_ignore);
// set the inital view visibility
@@ -597,10 +544,6 @@
return mNaturalBarHeight;
}
- private int getCloseViewHeight() {
- return mCloseViewHeight;
- }
-
private View.OnClickListener mRecentsClickListener = new View.OnClickListener() {
public void onClick(View v) {
toggleRecentApps();
@@ -1169,20 +1112,6 @@
}
}
- final Runnable mAnimationCallback = new Runnable() {
- @Override
- public void run() {
- doAnimation(mChoreographer.getFrameTimeNanos());
- }
- };
-
- final Runnable mRevealAnimationCallback = new Runnable() {
- @Override
- public void run() {
- doRevealAnimation(mChoreographer.getFrameTimeNanos());
- }
- };
-
View.OnFocusChangeListener mFocusChangeListener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
// Because 'v' is a ViewGroup, all its children will be (un)selected
@@ -1191,7 +1120,7 @@
}
};
- private void makeExpandedVisible(boolean revealAfterDraw) {
+ void makeExpandedVisible(boolean revealAfterDraw) {
if (SPEW) Slog.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
if (mExpandedVisible) {
return;
@@ -1218,38 +1147,20 @@
// Updating the window layout will force an expensive traversal/redraw.
// Kick off the reveal animation after this is complete to avoid animation latency.
if (revealAfterDraw) {
- mHandler.post(mStartRevealAnimation);
+// mHandler.post(mStartRevealAnimation);
}
visibilityChanged(true);
}
- public void animateExpand() {
- if (SPEW) Slog.d(TAG, "Animate expand: expanded=" + mExpanded);
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
- return ;
- }
- if (mExpanded) {
- return;
- }
-
- prepareTracking(0, true);
- mHandler.post(mPerformSelfExpandFling);
- }
-
public void animateCollapse() {
animateCollapse(CommandQueue.FLAG_EXCLUDE_NONE);
}
public void animateCollapse(int flags) {
- animateCollapse(flags, 1.0f);
- }
-
- public void animateCollapse(int flags, float velocityMultiplier) {
if (SPEW) {
- Slog.d(TAG, "animateCollapse(): mExpanded=" + mExpanded
+ Slog.d(TAG, "animateCollapse(): "
+ " mExpandedVisible=" + mExpandedVisible
- + " mExpanded=" + mExpanded
+ " mAnimating=" + mAnimating
+ " mAnimatingReveal=" + mAnimatingReveal
+ " mAnimY=" + mAnimY
@@ -1267,41 +1178,23 @@
mHandler.sendEmptyMessage(MSG_CLOSE_SEARCH_PANEL);
}
- if (!mExpandedVisible) {
- return;
- }
-
- int y;
- if (mAnimating || mAnimatingReveal) {
- y = (int)mAnimY;
- } else {
- y = getExpandedViewMaxHeight()-1;
- }
- // Let the fling think that we're open so it goes in the right direction
- // and doesn't try to re-open the windowshade.
- mExpanded = true;
- prepareTracking(y, false);
- performFling(y, -mSelfCollapseVelocityPx*velocityMultiplier, true);
+ mStatusBarView.collapseAllPanels(true);
}
- void performExpand() {
- if (SPEW) Slog.d(TAG, "performExpand: mExpanded=" + mExpanded);
+ @Override
+ public void animateExpand() {
+ if (SPEW) Slog.d(TAG, "animateExpand: mExpandedVisible=" + mExpandedVisible);
if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
return ;
}
- if (mExpanded) {
- return;
- }
- mExpanded = true;
- makeExpandedVisible(false);
- updateExpandedViewPos(EXPANDED_FULL_OPEN);
+ mNotificationPanel.expand();
if (false) postStartTracing();
}
- void performCollapse() {
- if (SPEW) Slog.d(TAG, "performCollapse: mExpanded=" + mExpanded
+ void makeExpandedInvisible() {
+ if (SPEW) Slog.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
+ " mExpandedVisible=" + mExpandedVisible);
if (!mExpandedVisible) {
@@ -1309,7 +1202,7 @@
}
// Ensure the panel is fully collapsed (just in case; bug 6765842)
- updateExpandedViewPos(0);
+ mStatusBarView.collapseAllPanels(/*animate=*/ false);
mExpandedVisible = false;
mPile.setLayoutTransitionsEnabled(false);
@@ -1329,11 +1222,6 @@
setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
}
- if (!mExpanded) {
- return;
- }
- mExpanded = false;
-
// Close any "App info" popups that might have snuck on-screen
dismissPopups();
@@ -1343,67 +1231,6 @@
}
}
- void resetLastAnimTime() {
- mAnimLastTimeNanos = System.nanoTime();
- if (SPEW) {
- Throwable t = new Throwable();
- t.fillInStackTrace();
- Slog.d(TAG, "resetting last anim time=" + mAnimLastTimeNanos, t);
- }
- }
-
- void doAnimation(long frameTimeNanos) {
- if (mAnimating) {
- if (SPEW) Slog.d(TAG, "doAnimation dt=" + (frameTimeNanos - mAnimLastTimeNanos));
- if (SPEW) Slog.d(TAG, "doAnimation before mAnimY=" + mAnimY);
- incrementAnim(frameTimeNanos);
- if (SPEW) {
- Slog.d(TAG, "doAnimation after mAnimY=" + mAnimY);
- Slog.d(TAG, "doAnimation expandedViewMax=" + getExpandedViewMaxHeight());
- }
-
- if (mAnimY >= getExpandedViewMaxHeight()-1 && !mClosing) {
- if (SPEW) Slog.d(TAG, "Animation completed to expanded state.");
- mAnimating = false;
- updateExpandedViewPos(EXPANDED_FULL_OPEN);
- performExpand();
- return;
- }
-
- if (mAnimY == 0 && mAnimAccel == 0 && mClosing) {
- if (SPEW) Slog.d(TAG, "Animation completed to collapsed state.");
- mAnimating = false;
- performCollapse();
- return;
- }
-
- if (mAnimY < getStatusBarHeight() && mClosing) {
- // Draw one more frame with the bar positioned at the top of the screen
- // before ending the animation so that the user sees the bar in
- // its final position. The call to performCollapse() causes a window
- // relayout which takes time and might cause the animation to skip
- // on the very last frame before the bar disappears if we did it now.
- mAnimY = 0;
- mAnimAccel = 0;
- mAnimVel = 0;
- }
-
- updateExpandedViewPos((int)mAnimY);
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- }
- }
-
- void stopTracking() {
- if (!mTracking)
- return;
- mTracking = false;
- setPileLayers(View.LAYER_TYPE_NONE);
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- mCloseView.setPressed(false);
- }
-
/**
* Enables or disables layers on the children of the notifications pile.
*
@@ -1451,148 +1278,6 @@
}
}
- void incrementAnim(long frameTimeNanos) {
- final long deltaNanos = Math.max(frameTimeNanos - mAnimLastTimeNanos, 0);
- final float t = deltaNanos * 0.000000001f; // ns -> s
- final float y = mAnimY;
- final float v = mAnimVel; // px/s
- final float a = mAnimAccel; // px/s/s
- mAnimY = y + (v*t) + (0.5f*a*t*t); // px
- mAnimVel = v + (a*t); // px/s
- mAnimLastTimeNanos = frameTimeNanos; // ns
- //Slog.d(TAG, "y=" + y + " v=" + v + " a=" + a + " t=" + t + " mAnimY=" + mAnimY
- // + " mAnimAccel=" + mAnimAccel);
- }
-
- void doRevealAnimation(long frameTimeNanos) {
- if (SPEW) {
- Slog.d(TAG, "doRevealAnimation: dt=" + (frameTimeNanos - mAnimLastTimeNanos));
- }
- final int h = mNotificationPanelMinHeight;
- if (mAnimatingReveal && mAnimating && mAnimY < h) {
- incrementAnim(frameTimeNanos);
- if (mAnimY >= h) {
- mAnimY = h;
- updateExpandedViewPos((int)mAnimY);
- } else {
- updateExpandedViewPos((int)mAnimY);
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
- mRevealAnimationCallback, null);
- }
- }
- }
-
- void prepareTracking(int y, boolean opening) {
- if (CHATTY) {
- Slog.d(TAG, "panel: beginning to track the user's touch, y=" + y + " opening=" + opening);
- }
-
- mCloseView.setPressed(true);
-
- mTracking = true;
- setPileLayers(View.LAYER_TYPE_HARDWARE);
- mVelocityTracker = VelocityTracker.obtain();
- if (opening) {
- makeExpandedVisible(true);
- } else {
- // it's open, close it?
- if (mAnimating) {
- mAnimating = false;
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- }
- updateExpandedViewPos(y + mViewDelta);
- }
- }
-
- void performFling(int y, float vel, boolean always) {
- if (CHATTY) {
- Slog.d(TAG, "panel: will fling, y=" + y + " vel=" + vel + " mExpanded=" + mExpanded);
- }
-
- mAnimatingReveal = false;
-
- mAnimY = y;
- mAnimVel = vel;
-
- //Slog.d(TAG, "starting with mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel);
-
- if (mExpanded) {
- if (!always && (
- vel > mFlingCollapseMinVelocityPx
- || (y > (getExpandedViewMaxHeight()*(1f-mCollapseMinDisplayFraction)) &&
- vel > -mFlingExpandMinVelocityPx))) {
- // We are expanded, but they didn't move sufficiently to cause
- // us to retract. Animate back to the expanded position.
- mAnimAccel = mExpandAccelPx;
- if (vel < 0) {
- mAnimVel = 0;
- }
- }
- else {
- // We are expanded and are now going to animate away.
- mAnimAccel = -mCollapseAccelPx;
- if (vel > 0) {
- mAnimVel = 0;
- }
- }
- } else {
- if (always || (
- vel > mFlingExpandMinVelocityPx
- || (y > (getExpandedViewMaxHeight()*(1f-mExpandMinDisplayFraction)) &&
- vel > -mFlingCollapseMinVelocityPx))) {
- // We are collapsed, and they moved enough to allow us to
- // expand. Animate in the notifications.
- mAnimAccel = mExpandAccelPx;
- if (vel < 0) {
- mAnimVel = 0;
- }
- }
- else {
- // We are collapsed, but they didn't move sufficiently to cause
- // us to retract. Animate back to the collapsed position.
- mAnimAccel = -mCollapseAccelPx;
- if (vel > 0) {
- mAnimVel = 0;
- }
- }
- }
- //Slog.d(TAG, "mAnimY=" + mAnimY + " mAnimVel=" + mAnimVel
- // + " mAnimAccel=" + mAnimAccel);
-
- resetLastAnimTime();
- mAnimating = true;
- mClosing = mAnimAccel < 0;
-
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- mChoreographer.removeCallbacks(Choreographer.CALLBACK_ANIMATION,
- mRevealAnimationCallback, null);
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION,
- mAnimationCallback, null);
- stopTracking();
- }
-
- boolean handleUniverseEvent(MotionEvent event) {
- if ((mDisabled & StatusBarManager.DISABLE_EXPAND) != 0) {
- return false;
- }
- if (mExpanded) {
- return false;
- }
- if (mUniverseBackground.consumeEvent(event)) {
- if (mTracking) {
- // fling back to the top, starting from the last tracked position.
- mFlingY = mTrackingPosition;
- mViewDelta = 0;
- mFlingVelocity = -1;
- mHandler.post(mPerformFling);
- }
- return true;
- }
- return false;
- }
-
boolean interceptTouchEvent(MotionEvent event) {
if (SPEW) {
Slog.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled="
@@ -1612,104 +1297,11 @@
return false;
}
- final int y = (int)event.getRawY();
- final int action = event.getAction();
- final int statusBarSize = getStatusBarHeight();
- final int hitSize = statusBarSize*2;
- if (action == MotionEvent.ACTION_DOWN) {
- if (!areLightsOn()) {
- setLightsOn(true);
- }
-
- if (!mExpanded) {
- mViewDelta = statusBarSize - y;
- } else {
- mCloseView.getLocationOnScreen(mAbsPos);
- mViewDelta = mAbsPos[1]
- + getCloseViewHeight() // XXX: not closeViewHeight, but paddingBottom from the 9patch
- + mNotificationPanelBackgroundPadding.top
- + mNotificationPanelBackgroundPadding.bottom
- - y;
- }
- if ((!mExpanded && y < hitSize) ||
- // @@ add taps outside the panel if it's not full-screen
- (mExpanded && y > (getExpandedViewMaxHeight()-hitSize))) {
- // We drop events at the edge of the screen to make the windowshade come
- // down by accident less, especially when pushing open a device with a keyboard
- // that rotates (like g1 and droid)
- int x = (int)event.getRawX();
- final int edgeBorder = mEdgeBorder;
- if (x >= edgeBorder && x < mDisplayMetrics.widthPixels - edgeBorder) {
- prepareTracking(y, !mExpanded);// opening if we're not already fully visible
- trackMovement(event);
- mGestureRec.tag("tracking", mExpanded ? "expanded" : "collapsed");
- }
- }
- } else if (mTracking) {
- trackMovement(event);
- if (action == MotionEvent.ACTION_MOVE) {
- if (mAnimatingReveal && (y + mViewDelta) < mNotificationPanelMinHeight) {
- // nothing
- } else {
- mAnimatingReveal = false;
- updateExpandedViewPos(y + mViewDelta);
- }
- } else if (action == MotionEvent.ACTION_UP
- || action == MotionEvent.ACTION_CANCEL) {
- mVelocityTracker.computeCurrentVelocity(1000);
-
- float yVel = mVelocityTracker.getYVelocity();
- boolean negative = yVel < 0;
-
- float xVel = mVelocityTracker.getXVelocity();
- if (xVel < 0) {
- xVel = -xVel;
- }
- if (xVel > mFlingGestureMaxXVelocityPx) {
- xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis
- }
-
- float vel = (float)Math.hypot(yVel, xVel);
- if (vel > mFlingGestureMaxOutputVelocityPx) {
- vel = mFlingGestureMaxOutputVelocityPx;
- }
- if (negative) {
- vel = -vel;
- }
-
- if (CHATTY) {
- Slog.d(TAG, String.format("gesture: vraw=(%f,%f) vnorm=(%f,%f) vlinear=%f",
- mVelocityTracker.getXVelocity(),
- mVelocityTracker.getYVelocity(),
- xVel, yVel,
- vel));
- }
-
- if (mTrackingPosition == mNotificationPanelMinHeight) {
- // start the fling from the tracking position, ignore y and view delta
- mFlingY = mTrackingPosition;
- mViewDelta = 0;
- } else {
- mFlingY = y;
- }
- mFlingVelocity = vel;
- mGestureRec.tag("fling " + ((mFlingVelocity > 0) ? "open" : "closed"),
- "v=" + mFlingVelocity);
- mHandler.post(mPerformFling);
- }
-
- }
return false;
}
- private void trackMovement(MotionEvent event) {
- // Add movement to velocity tracker using raw screen X and Y coordinates instead
- // of window coordinates because the window frame may be moving at the same time.
- float deltaX = event.getRawX() - event.getX();
- float deltaY = event.getRawY() - event.getY();
- event.offsetLocation(deltaX, deltaY);
- mVelocityTracker.addMovement(event);
- event.offsetLocation(-deltaX, -deltaY);
+ public GestureRecorder getGestureRecorder() {
+ return mGestureRec;
}
@Override // CommandQueue
@@ -1913,8 +1505,7 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
synchronized (mQueueLock) {
pw.println("Current Status Bar state:");
- pw.println(" mExpanded=" + mExpanded
- + ", mExpandedVisible=" + mExpandedVisible
+ pw.println(" mExpandedVisible=" + mExpandedVisible
+ ", mTrackingPosition=" + mTrackingPosition);
pw.println(" mTicking=" + mTicking);
pw.println(" mTracking=" + mTracking);
@@ -1930,7 +1521,6 @@
+ " mViewDelta=" + mViewDelta);
pw.println(" mDisplayMetrics=" + mDisplayMetrics);
pw.println(" mPile: " + viewInfo(mPile));
- pw.println(" mCloseView: " + viewInfo(mCloseView));
pw.println(" mTickerView: " + viewInfo(mTickerView));
pw.println(" mScrollView: " + viewInfo(mScrollView)
+ " scroll " + mScrollView.getScrollX() + "," + mScrollView.getScrollY());
@@ -2039,83 +1629,13 @@
}
@Override
- protected void updateExpandedViewPos(int expandedPosition) {
- if (SPEW) {
- Slog.d(TAG, "updateExpandedViewPos: expandedPosition=" + expandedPosition
- //+ " mTrackingParams.y=" + ((mTrackingParams == null) ? "?" : mTrackingParams.y)
- + " mTracking=" + mTracking
- + " mTrackingPosition=" + mTrackingPosition
- + " mExpandedVisible=" + mExpandedVisible
- + " mAnimating=" + mAnimating
- + " mAnimatingReveal=" + mAnimatingReveal
- + " mClosing=" + mClosing
- + " gravity=" + mNotificationPanelGravity);
- }
- int panelh = 0;
- final int disph = getExpandedViewMaxHeight();
-
- // If the expanded view is not visible, make sure they're still off screen.
- // Maybe the view was resized.
- if (!mExpandedVisible) {
- if (SPEW) Slog.d(TAG, "updateExpandedViewPos: view not visible, bailing");
- updateExpandedInvisiblePosition();
- return;
- }
-
- // tracking view...
- if (expandedPosition == EXPANDED_FULL_OPEN) {
- panelh = disph;
- }
- else if (expandedPosition == EXPANDED_LEAVE_ALONE) {
- panelh = mTrackingPosition;
- }
- else {
- if (expandedPosition <= disph) {
- panelh = expandedPosition;
- } else {
- panelh = disph;
- }
- }
-
- // catch orientation changes and other peculiar cases
- if (panelh > 0 &&
- ((panelh > disph) ||
- (panelh < disph && !mTracking && !mAnimating))) {
- if (SPEW) Slog.d(TAG, "updateExpandedViewPos: orientation change?");
- panelh = disph;
- } else if (panelh < 0) {
- panelh = 0;
- }
-
- if (SPEW) Slog.d(TAG, "updateExpandedViewPos: adjusting size to panelh=" + panelh);
-
- if (panelh == mTrackingPosition) {
- if (SPEW) Slog.d(TAG, "updateExpandedViewPos: panelh == mTrackingPosition, bailing");
- return;
- }
-
- mTrackingPosition = panelh;
-
+ public void updateExpandedViewPos(int thingy) {
+ // TODO
+ if (DEBUG) Slog.v(TAG, "updateExpandedViewPos");
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mNotificationPanel.getLayoutParams();
- lp.height = panelh;
lp.gravity = mNotificationPanelGravity;
lp.leftMargin = mNotificationPanelMarginLeftPx;
- if (SPEW) {
- Slog.v(TAG, "updated cropView height=" + panelh + " grav=" + lp.gravity);
- }
mNotificationPanel.setLayoutParams(lp);
-
- final int barh = getCloseViewHeight() + getStatusBarHeight();
- final float frac = saturate((float)(panelh - barh) / (disph - barh));
-
- if (DIM_BEHIND_EXPANDED_PANEL && ActivityManager.isHighEndGfx(mDisplay)) {
- // woo, special effects
- final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
- final int color = ((int)(0xB0 * k)) << 24;
- mStatusBarWindow.setBackgroundColor(color);
- }
-
- updateCarrierLabelVisibility(false);
}
// called by makeStatusbar and also by PhoneStatusBarView
@@ -2196,6 +1716,9 @@
mPostCollapseCleanup = new Runnable() {
@Override
public void run() {
+ if (DEBUG) {
+ Slog.v(TAG, "running post-collapse cleanup");
+ }
try {
mPile.setViewRemoval(true);
mBarService.onClearAllNotifications();
@@ -2264,7 +1787,7 @@
}
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
// no waiting!
- performCollapse();
+ makeExpandedInvisible();
}
else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(action)) {
updateResources();
@@ -2416,7 +1939,7 @@
@Override
protected boolean shouldDisableNavbarGestures() {
- return mExpanded || (mDisabled & StatusBarManager.DISABLE_HOME) != 0;
+ return mExpandedVisible || (mDisabled & StatusBarManager.DISABLE_HOME) != 0;
}
private static class FastColorDrawable extends Drawable {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index fd4cff8..6de0153 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -16,9 +16,12 @@
package com.android.systemui.statusbar.phone;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.Resources;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Rect;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -35,133 +38,23 @@
import com.android.systemui.statusbar.BaseStatusBar;
import com.android.systemui.statusbar.policy.FixedSizeDrawable;
-public class PhoneStatusBarView extends FrameLayout {
+public class PhoneStatusBarView extends PanelBar {
private static final String TAG = "PhoneStatusBarView";
-
- static final int DIM_ANIM_TIME = 400;
-
- PhoneStatusBar mService;
- boolean mTracking;
- int mStartX, mStartY;
- ViewGroup mNotificationIcons;
- ViewGroup mStatusIcons;
-
- boolean mNightMode = false;
- int mStartAlpha = 0, mEndAlpha = 0;
- long mEndTime = 0;
-
- Rect mButtonBounds = new Rect();
- boolean mCapturingEvents = true;
+ PhoneStatusBar mBar;
+ int mScrimColor;
public PhoneStatusBarView(Context context, AttributeSet attrs) {
super(context, attrs);
}
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mNotificationIcons = (ViewGroup)findViewById(R.id.notificationIcons);
- mStatusIcons = (ViewGroup)findViewById(R.id.statusIcons);
+ public void setBar(PhoneStatusBar bar) {
+ mBar = bar;
}
@Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- //mService.onBarViewAttached();
- }
-
- @Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- mService.updateDisplaySize();
- boolean nightMode = (newConfig.uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
- if (mNightMode != nightMode) {
- mNightMode = nightMode;
- mStartAlpha = getCurAlpha();
- mEndAlpha = mNightMode ? 0x80 : 0x00;
- mEndTime = SystemClock.uptimeMillis() + DIM_ANIM_TIME;
- invalidate();
- }
- }
-
- int getCurAlpha() {
- long time = SystemClock.uptimeMillis();
- if (time > mEndTime) {
- return mEndAlpha;
- }
- return mEndAlpha
- - (int)(((mEndAlpha-mStartAlpha) * (mEndTime-time) / DIM_ANIM_TIME));
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w, h, oldw, oldh);
- mService.updateExpandedViewPos(BaseStatusBar.EXPANDED_LEAVE_ALONE);
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- super.onLayout(changed, l, t, r, b);
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- int alpha = getCurAlpha();
- if (alpha != 0) {
- canvas.drawARGB(alpha, 0, 0, 0);
- }
- if (alpha != mEndAlpha) {
- invalidate();
- }
- }
-
- /**
- * Gets the left position of v in this view. Throws if v is not
- * a child of this.
- */
- private int getViewOffset(View v) {
- int offset = 0;
- while (v != this) {
- offset += v.getLeft();
- ViewParent p = v.getParent();
- if (v instanceof View) {
- v = (View)p;
- } else {
- throw new RuntimeException(v + " is not a child of " + this);
- }
- }
- return offset;
- }
-
- /**
- * Ensure that, if there is no target under us to receive the touch,
- * that we process it ourself. This makes sure that onInterceptTouchEvent()
- * is always called for the entire gesture.
- */
- @Override
- public boolean onTouchEvent(MotionEvent event) {
- if (!mCapturingEvents) {
- return false;
- }
- if (event.getAction() != MotionEvent.ACTION_DOWN) {
- mService.interceptTouchEvent(event);
- }
- return true;
- }
-
- @Override
- public boolean onInterceptTouchEvent(MotionEvent event) {
- if (event.getAction() == MotionEvent.ACTION_DOWN) {
- if (mButtonBounds.contains((int)event.getX(), (int)event.getY())) {
- mCapturingEvents = false;
- return false;
- }
- }
- mCapturingEvents = true;
- return mService.interceptTouchEvent(event)
- ? true : super.onInterceptTouchEvent(event);
+ public void onAttachedToWindow() {
+ Resources res = getContext().getResources();
+ mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
}
@Override
@@ -178,4 +71,43 @@
}
return false;
}
+
+ @Override
+ public void onPanelPeeked() {
+ super.onPanelPeeked();
+ mBar.makeExpandedVisible(true);
+ }
+
+ @Override
+ public void onAllPanelsCollapsed() {
+ super.onAllPanelsCollapsed();
+ mBar.makeExpandedInvisible();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return mBar.interceptTouchEvent(event) || super.onTouchEvent(event);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent event) {
+ return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event);
+ }
+
+ @Override
+ public void panelExpansionChanged(PanelView pv, float frac) {
+ super.panelExpansionChanged(pv, frac);
+
+ if (mScrimColor != 0 && ActivityManager.isHighEndGfx(mBar.mDisplay)) {
+ // woo, special effects
+ final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2.2f))));
+ // attenuate background color alpha by k
+ final int color = (int) ((float)(mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
+ mBar.mStatusBarWindow.setBackgroundColor(color);
+ }
+
+ mBar.updateCarrierLabelVisibility(false);
+ }
+
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index f53ed0c..2d4c9ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -37,8 +37,6 @@
private ExpandHelper mExpandHelper;
private NotificationRowLayout latestItems;
- private boolean mUniverseHandling = false;
-
PhoneStatusBar mService;
public StatusBarWindowView(Context context, AttributeSet attrs) {
@@ -73,16 +71,6 @@
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mService.handleUniverseEvent(ev)) {
- mUniverseHandling = true;
- MotionEvent cancellation = MotionEvent.obtain(ev);
- cancellation.setAction(MotionEvent.ACTION_CANCEL);
- mExpandHelper.onInterceptTouchEvent(cancellation);
- latestItems.onInterceptTouchEvent(cancellation);
- cancellation.recycle();
- return true;
- }
-
boolean intercept = mExpandHelper.onInterceptTouchEvent(ev) ||
super.onInterceptTouchEvent(ev);
if (intercept) {
@@ -96,12 +84,6 @@
@Override
public boolean onTouchEvent(MotionEvent ev) {
- if (mUniverseHandling) {
- if (!mService.handleUniverseEvent(ev)) {
- mUniverseHandling = false;
- }
- return true;
- }
boolean handled = mExpandHelper.onTouchEvent(ev) ||
super.onTouchEvent(ev);
return handled;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
index 69872df..ffc18c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/Clock.java
@@ -34,6 +34,7 @@
import android.text.style.RelativeSizeSpan;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
+import android.util.Slog;
import android.view.View;
import android.widget.TextView;
@@ -173,7 +174,6 @@
+ "a" + MAGIC2 + format.substring(b + 1);
}
}
-
mClockFormat = sdf = new SimpleDateFormat(format);
mClockFormatString = format;
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
index 9fee49b..e63735677 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -166,6 +166,7 @@
}
public void onChildDismissed(View v) {
+ if (DEBUG) Slog.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
final View veto = v.findViewById(R.id.veto);
if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
veto.performClick();
@@ -229,6 +230,7 @@
* get removed properly.
*/
public void setViewRemoval(boolean removeViews) {
+ if (DEBUG) Slog.v(TAG, "setViewRemoval: " + removeViews);
mRemoveViews = removeViews;
}
diff --git a/policy/src/com/android/internal/policy/impl/LockScreen.java b/policy/src/com/android/internal/policy/impl/LockScreen.java
index 82181d3..8645172 100644
--- a/policy/src/com/android/internal/policy/impl/LockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/LockScreen.java
@@ -32,6 +32,7 @@
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.os.UserId;
import android.os.Vibrator;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -275,7 +276,8 @@
// Update the search icon with drawable from the search .apk
if (!mSearchDisabled) {
- Intent intent = SearchManager.getAssistIntent(mContext);
+ Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, UserId.USER_CURRENT);
if (intent != null) {
// XXX Hack. We need to substitute the icon here but haven't formalized
// the public API. The "_google" metadata will be going away, so
@@ -309,7 +311,9 @@
final int resId = mGlowPadView.getResourceIdForTarget(target);
switch (resId) {
case com.android.internal.R.drawable.ic_action_assist_generic:
- Intent assistIntent = SearchManager.getAssistIntent(mContext);
+ Intent assistIntent =
+ ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, UserId.USER_CURRENT);
if (assistIntent != null) {
launchActivity(assistIntent);
} else {
@@ -335,6 +339,10 @@
}
}
+ /**
+ * Launches the said intent for the current foreground user.
+ * @param intent
+ */
private void launchActivity(Intent intent) {
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
@@ -346,7 +354,7 @@
Log.w(TAG, "can't dismiss keyguard on launch");
}
try {
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent, UserId.USER_CURRENT);
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Activity not found for intent + " + intent.getAction());
}
@@ -522,7 +530,9 @@
} else if (disabledBySimState) {
Log.v(TAG, "Camera disabled by Sim State");
}
- boolean searchActionAvailable = SearchManager.getAssistIntent(mContext) != null;
+ boolean searchActionAvailable =
+ ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, UserId.USER_CURRENT) != null;
mCameraDisabled = disabledByAdmin || disabledBySimState || !cameraTargetPresent;
mSearchDisabled = disabledBySimState || !searchActionAvailable || !searchTargetPresent;
mUnlockWidgetMethods.updateResources();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 8c627a3..769b513 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -55,6 +55,7 @@
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UEventObserver;
+import android.os.UserId;
import android.os.Vibrator;
import android.provider.Settings;
@@ -2110,7 +2111,7 @@
if (searchManager != null) {
searchManager.stopSearch();
}
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent, UserId.USER_CURRENT);
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "No activity to handle assist long press action.", e);
}
@@ -2118,13 +2119,14 @@
private void launchAssistAction() {
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
- Intent intent = SearchManager.getAssistIntent(mContext);
+ Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
+ .getAssistIntent(mContext, UserId.USER_CURRENT);
if (intent != null) {
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
try {
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent, UserId.USER_CURRENT);
} catch (ActivityNotFoundException e) {
Slog.w(TAG, "No activity to handle assist action.", e);
}
diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java
old mode 100644
new mode 100755
index cc9b9fa..4c98ac3
--- a/services/java/com/android/server/BluetoothManagerService.java
+++ b/services/java/com/android/server/BluetoothManagerService.java
@@ -22,6 +22,7 @@
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.Binder;
import android.provider.Settings;
import android.util.Log;
import java.util.List;
@@ -66,6 +67,7 @@
private IBluetooth mBluetooth;
private boolean mBinding;
private boolean mUnbinding;
+ private boolean mQuietEnable = false;
private void registerForAirplaneMode(IntentFilter filter) {
final ContentResolver resolver = mContext.getContentResolver();
@@ -105,7 +107,7 @@
} else {
if (isBluetoothPersistedStateOn()) {
// enable without persisting the setting
- handleEnable(false);
+ handleEnable(false, false);
}
}
}
@@ -269,7 +271,32 @@
Message msg = mHandler.obtainMessage(MESSAGE_GET_NAME_AND_ADDRESS);
mHandler.sendMessage(msg);
}
+ public boolean enableNoAutoConnect()
+ {
+ mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
+ "Need BLUETOOTH ADMIN permission");
+ if (DBG) {
+ Log.d(TAG,"enableNoAutoConnect(): mBluetooth =" + mBluetooth +
+ " mBinding = " + mBinding);
+ }
+ if (Binder.getCallingUid() != android.os.Process.NFC_UID) {
+ throw new SecurityException("no permission to enable Bluetooth quietly");
+ }
+ synchronized(mConnection) {
+ if (mBinding) {
+ Log.w(TAG,"enableNoAutoConnect(): binding in progress. Returning..");
+ return true;
+ }
+ if (mConnection == null) mBinding = true;
+ }
+ Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
+ msg.arg1=0; //No persist
+ msg.arg2=1; //Quiet mode
+ mHandler.sendMessage(msg);
+ return true;
+
+ }
public boolean enable() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH ADMIN permission");
@@ -288,6 +315,7 @@
Message msg = mHandler.obtainMessage(MESSAGE_ENABLE);
msg.arg1=1; //persist
+ msg.arg2=0; //No Quiet Mode
mHandler.sendMessage(msg);
return true;
}
@@ -501,7 +529,7 @@
Log.d(TAG, "MESSAGE_ENABLE: mBluetooth = " + mBluetooth);
}
- handleEnable(msg.arg1 == 1);
+ handleEnable(msg.arg1 == 1, msg.arg2 ==1);
break;
case MESSAGE_DISABLE:
@@ -574,14 +602,21 @@
//Do enable request
try {
- if(!mBluetooth.enable()) {
- Log.e(TAG,"IBluetooth.enable() returned false");
+ if (mQuietEnable == false) {
+ if(!mBluetooth.enable()) {
+ Log.e(TAG,"IBluetooth.enable() returned false");
+ }
+ }
+ else
+ {
+ if(!mBluetooth.enableNoAutoConnect()) {
+ Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+ }
}
} catch (RemoteException e) {
Log.e(TAG,"Unable to call enable()",e);
}
}
-
break;
}
case MESSAGE_TIMEOUT_BIND: {
@@ -637,11 +672,13 @@
}
};
- private void handleEnable(boolean persist) {
+ private void handleEnable(boolean persist, boolean quietMode) {
if (persist) {
persistBluetoothSetting(true);
}
+ mQuietEnable = quietMode;
+
synchronized(mConnection) {
if (mBluetooth == null) {
//Start bind timeout and bind
@@ -664,8 +701,15 @@
//Enable bluetooth
try {
- if(!mBluetooth.enable()) {
- Log.e(TAG,"IBluetooth.enable() returned false");
+ if (!mQuietEnable) {
+ if(!mBluetooth.enable()) {
+ Log.e(TAG,"IBluetooth.enable() returned false");
+ }
+ }
+ else {
+ if(!mBluetooth.enableNoAutoConnect()) {
+ Log.e(TAG,"IBluetooth.enableNoAutoConnect() returned false");
+ }
}
} catch (RemoteException e) {
Log.e(TAG,"Unable to call enable()",e);
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java
index 7dde340..9b3459b 100644
--- a/services/java/com/android/server/usb/UsbSettingsManager.java
+++ b/services/java/com/android/server/usb/UsbSettingsManager.java
@@ -545,6 +545,10 @@
defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device));
}
+ // Send broadcast to running activity with registered intent
+ mContext.sendBroadcast(intent);
+
+ // Start activity with registered intent
resolveActivity(intent, matches, defaultPackage, device, null);
}
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 9acffa3..36f2c14 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -28,6 +28,7 @@
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
@@ -477,6 +478,11 @@
}
@Override
+ public Context createConfigurationContext(Configuration overrideConfiguration) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public boolean isRestricted() {
throw new UnsupportedOperationException();
}
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index 0ec1f13..0577dbb 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -40,12 +40,16 @@
import android.view.MenuItem;
import android.view.View;
import android.content.Context;
+import android.content.res.Configuration;
import android.util.Log;
public class ActivityTestMain extends Activity {
static final String TAG = "ActivityTest";
+ static final String KEY_CONFIGURATION = "configuration";
+
ActivityManager mAm;
+ Configuration mOverrideConfig;
class BroadcastResultReceiver extends BroadcastReceiver {
@Override
@@ -111,6 +115,12 @@
super.onCreate(savedInstanceState);
mAm = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
+ if (savedInstanceState != null) {
+ mOverrideConfig = savedInstanceState.getParcelable(KEY_CONFIGURATION);
+ if (mOverrideConfig != null) {
+ applyOverrideConfiguration(mOverrideConfig);
+ }
+ }
}
@Override
@@ -182,6 +192,21 @@
return true;
}
});
+ menu.add("Density!").setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override public boolean onMenuItemClick(MenuItem item) {
+ if (mOverrideConfig == null) {
+ mOverrideConfig = new Configuration();
+ }
+ if (mOverrideConfig.densityDpi == Configuration.DENSITY_DPI_UNDEFINED) {
+ mOverrideConfig.densityDpi = (getApplicationContext().getResources()
+ .getConfiguration().densityDpi*2)/3;
+ } else {
+ mOverrideConfig.densityDpi = Configuration.DENSITY_DPI_UNDEFINED;
+ }
+ recreate();
+ return true;
+ }
+ });
return true;
}
@@ -191,6 +216,14 @@
buildUi();
}
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (mOverrideConfig != null) {
+ outState.putParcelable(KEY_CONFIGURATION, mOverrideConfig);
+ }
+ }
+
private View scrollWrap(View view) {
ScrollView scroller = new ScrollView(this);
scroller.addView(view, new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT,
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 1857033..c783ad6 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -177,6 +177,15 @@
</activity>
<activity
+ android:name="GlyphCacheActivity"
+ android:label="_GlyphCache">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="CanvasTextureViewActivity"
android:label="_CanvasTextureView">
<intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java
new file mode 100644
index 0000000..e89b294
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GlyphCacheActivity.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.hwui;
+
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+import static android.widget.LinearLayout.LayoutParams;
+
+public class GlyphCacheActivity extends Activity {
+
+ private static final String mCharacterSet = "abcdefghijklmnopqrstuvwxyz" +
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "~!@#$%^&*()_+-={}[]:\";'<>?,./";
+ private int mTotalChars = 0;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ ScrollView scrollView = new ScrollView(this);
+ scrollView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.MATCH_PARENT));
+ LinearLayout layout = new LinearLayout(this);
+ layout.setOrientation(LinearLayout.VERTICAL);
+ layout.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ scrollView.addView(layout);
+
+ while (mTotalChars < 10000) {
+ layout.addView(createTextView());
+ }
+ setContentView(scrollView);
+ }
+
+ private TextView createTextView() {
+ TextView textview = new TextView(this);
+ textview.setTextSize(6 + (int) (Math.random() * 5) * 10);
+ textview.setTextColor(0xff << 24 | (int) (Math.random() * 255) << 16 |
+ (int) (Math.random() * 255) << 8 | (int) (Math.random() * 255) << 16);
+ textview.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ int numChars = 5 + (int) (Math.random() * 10);
+ mTotalChars += numChars;
+ textview.setText(createString(numChars));
+
+ return textview;
+ }
+
+ private String createString(int length) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < length; i++) {
+ sb.append(mCharacterSet.charAt((int)(Math.random() * mCharacterSet.length())));
+ }
+ return sb.toString();
+ }
+}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
index 7cd485e..3eec7f5 100644
--- a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/ImageProcessingActivity.java
@@ -167,6 +167,9 @@
case 14:
mTest = new GroupTest(false);
break;
+ case 15:
+ mTest = new Intrinsics(0);
+ break;
}
mTest.createBaseTest(this, mBitmapIn);
@@ -179,7 +182,7 @@
}
void setupTests() {
- mTestNames = new String[15];
+ mTestNames = new String[16];
mTestNames[0] = "Levels Vec3 Relaxed";
mTestNames[1] = "Levels Vec4 Relaxed";
mTestNames[2] = "Levels Vec3 Full";
@@ -195,6 +198,7 @@
mTestNames[12] = "Vignette Approximate Relaxed";
mTestNames[13] = "Group Test (emulated)";
mTestNames[14] = "Group Test (native)";
+ mTestNames[15] = "Intrinsics Convolve 3x3";
mTestSpinner.setAdapter(new ArrayAdapter<String>(
this, R.layout.spinner_layout, mTestNames));
}
diff --git a/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Intrinsics.java b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Intrinsics.java
new file mode 100644
index 0000000..ea8a018
--- /dev/null
+++ b/tests/RenderScriptTests/ImageProcessing/src/com/android/rs/image/Intrinsics.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.rs.image;
+
+import java.lang.Math;
+
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.Script;
+import android.renderscript.ScriptIntrinsicConvolve3x3;
+import android.renderscript.Type;
+import android.util.Log;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class Intrinsics extends TestBase {
+ private ScriptIntrinsicConvolve3x3 mScript;
+
+ Intrinsics(int id) {
+ }
+
+ public boolean onBar1Setup(SeekBar b, TextView t) {
+ t.setText("Strength");
+ b.setProgress(50);
+ return true;
+ }
+
+ public void onBar1Changed(int progress) {
+ float s = progress / 100.0f;
+ float v[] = new float[9];
+ v[0] = 0.f; v[1] = -s; v[2] = 0.f;
+ v[3] = -s; v[4] = s*4+1; v[5] = -s;
+ v[6] = 0.f; v[7] = -s; v[8] = 0.f;
+ mScript.setValues(v);
+ }
+
+
+ public void createTest(android.content.res.Resources res) {
+ mScript = ScriptIntrinsicConvolve3x3.create(mRS, Element.RGBA_8888(mRS));
+ }
+
+ public void runTest() {
+ mScript.forEach(mInPixelsAllocation, mOutPixelsAllocation);
+ }
+
+}
+
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index c4a6906..0a1191b 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -917,6 +917,12 @@
}
@Override
+ public Context createConfigurationContext(Configuration overrideConfiguration) {
+ // pass
+ return null;
+ }
+
+ @Override
public String[] databaseList() {
// pass
return null;
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index 3e20756..32261de 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -47,37 +47,19 @@
public int frequency;
/**
- * Time Synchronization Function (tsf) timestamp in microseconds when
- * this result was last seen.
- */
- public long timestamp;
-
- /**
* We'd like to obtain the following attributes,
* but they are not reported via the socket
* interface, even though they are known
* internally by wpa_supplicant.
* {@hide}
*/
- public ScanResult(String SSID, String BSSID, String caps, int level, int frequency, long tsf) {
+ public ScanResult(String SSID, String BSSID, String caps, int level, int frequency) {
this.SSID = SSID;
this.BSSID = BSSID;
this.capabilities = caps;
this.level = level;
this.frequency = frequency;
- this.timestamp = tsf;
- }
-
- /** copy constructor {@hide} */
- public ScanResult(ScanResult source) {
- if (source != null) {
- SSID = source.SSID;
- BSSID = source.BSSID;
- capabilities = source.capabilities;
- level = source.level;
- frequency = source.frequency;
- timestamp = source.timestamp;
- }
+ //networkConfig = null;
}
@Override
@@ -94,9 +76,7 @@
append(", level: ").
append(level).
append(", frequency: ").
- append(frequency).
- append(", timestamp: ").
- append(timestamp);
+ append(frequency);
return sb.toString();
}
@@ -113,7 +93,6 @@
dest.writeString(capabilities);
dest.writeInt(level);
dest.writeInt(frequency);
- dest.writeLong(timestamp);
}
/** Implement the Parcelable interface {@hide} */
@@ -125,8 +104,7 @@
in.readString(),
in.readString(),
in.readInt(),
- in.readInt(),
- in.readLong()
+ in.readInt()
);
}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 1b7e378..84c565b 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -197,22 +197,8 @@
return null;
}
- /**
- * Format of results:
- * =================
- * bssid=68:7f:74:d7:1b:6e
- * freq=2412
- * level=-43
- * tsf=1344621975160944
- * age=2623
- * flags=[WPA2-PSK-CCMP][WPS][ESS]
- * ssid=zubyb
- *
- * RANGE=ALL gets all scan results
- * MASK=<N> see wpa_supplicant/src/common/wpa_ctrl.h for details
- */
public String scanResults() {
- return doStringCommand("BSS RANGE=ALL MASK=0x1986");
+ return doStringCommand("SCAN_RESULTS");
}
public boolean startDriver() {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index bdb02c5..28c1c5c 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -891,13 +891,7 @@
* TODO: doc
*/
public List<ScanResult> syncGetScanResultsList() {
- synchronized (mScanResultCache) {
- List<ScanResult> scanList = new ArrayList<ScanResult>();
- for(ScanResult result: mScanResults) {
- scanList.add(new ScanResult(result));
- }
- return scanList;
- }
+ return mScanResults;
}
/**
@@ -1363,103 +1357,131 @@
mContext.sendStickyBroadcast(intent);
}
- private static final String BSSID_STR = "bssid=";
- private static final String FREQ_STR = "freq=";
- private static final String LEVEL_STR = "level=";
- private static final String TSF_STR = "tsf=";
- private static final String FLAGS_STR = "flags=";
- private static final String SSID_STR = "ssid=";
- private static final String DELIMITER_STR = "====";
/**
- * Format:
- * bssid=68:7f:76:d7:1a:6e
- * freq=2412
- * level=-44
- * tsf=1344626243700342
- * flags=[WPA2-PSK-CCMP][WPS][ESS]
- * ssid=zfdy
- * ====
- * bssid=68:5f:74:d7:1a:6f
- * freq=5180
- * level=-73
- * tsf=1344626243700373
- * flags=[WPA2-PSK-CCMP][WPS][ESS]
- * ssid=zuby
- * ====
+ * Parse the scan result line passed to us by wpa_supplicant (helper).
+ * @param line the line to parse
+ * @return the {@link ScanResult} object
*/
- private void setScanResults(String scanResults) {
- String bssid = "";
- int level = 0;
- int freq = 0;
- long tsf = 0;
- String flags = "";
- String ssid = "";
-
- if (scanResults == null) {
- return;
- }
-
- synchronized(mScanResultCache) {
- mScanResults = new ArrayList<ScanResult>();
- String[] lines = scanResults.split("\n");
-
- for (String line : lines) {
- if (line.startsWith(BSSID_STR)) {
- bssid = line.substring(BSSID_STR.length());
- } else if (line.startsWith(FREQ_STR)) {
+ private ScanResult parseScanResult(String line) {
+ ScanResult scanResult = null;
+ if (line != null) {
+ /*
+ * Cache implementation (LinkedHashMap) is not synchronized, thus,
+ * must synchronized here!
+ */
+ synchronized (mScanResultCache) {
+ String[] result = scanResultPattern.split(line);
+ if (3 <= result.length && result.length <= 5) {
+ String bssid = result[0];
+ // bssid | frequency | level | flags | ssid
+ int frequency;
+ int level;
try {
- freq = Integer.parseInt(line.substring(FREQ_STR.length()));
- } catch (NumberFormatException e) {
- freq = 0;
- }
- } else if (line.startsWith(LEVEL_STR)) {
- try {
- level = Integer.parseInt(line.substring(LEVEL_STR.length()));
+ frequency = Integer.parseInt(result[1]);
+ level = Integer.parseInt(result[2]);
/* some implementations avoid negative values by adding 256
* so we need to adjust for that here.
*/
if (level > 0) level -= 256;
- } catch(NumberFormatException e) {
+ } catch (NumberFormatException e) {
+ frequency = 0;
level = 0;
}
- } else if (line.startsWith(TSF_STR)) {
- try {
- tsf = Long.parseLong(line.substring(TSF_STR.length()));
- } catch (NumberFormatException e) {
- tsf = 0;
- }
- } else if (line.startsWith(FLAGS_STR)) {
- flags = line.substring(FLAGS_STR.length());
- } else if (line.startsWith(SSID_STR)) {
- ssid = line.substring(SSID_STR.length());
- if (ssid == null) ssid = "";
- } else if (line.startsWith(DELIMITER_STR)) {
- if (bssid != null) {
- String key = bssid + ssid;
- ScanResult scanResult = mScanResultCache.get(key);
- if (scanResult != null) {
- scanResult.level = level;
- scanResult.SSID = ssid;
- scanResult.capabilities = flags;
- scanResult.frequency = freq;
- scanResult.timestamp = tsf;
+
+ /*
+ * The formatting of the results returned by
+ * wpa_supplicant is intended to make the fields
+ * line up nicely when printed,
+ * not to make them easy to parse. So we have to
+ * apply some heuristics to figure out which field
+ * is the SSID and which field is the flags.
+ */
+ String ssid;
+ String flags;
+ if (result.length == 4) {
+ if (result[3].charAt(0) == '[') {
+ flags = result[3];
+ ssid = "";
} else {
+ flags = "";
+ ssid = result[3];
+ }
+ } else if (result.length == 5) {
+ flags = result[3];
+ ssid = result[4];
+ } else {
+ // Here, we must have 3 fields: no flags and ssid
+ // set
+ flags = "";
+ ssid = "";
+ }
+
+ // bssid + ssid is the hash key
+ String key = bssid + ssid;
+ scanResult = mScanResultCache.get(key);
+ if (scanResult != null) {
+ scanResult.level = level;
+ scanResult.SSID = ssid;
+ scanResult.capabilities = flags;
+ scanResult.frequency = frequency;
+ } else {
+ // Do not add scan results that have no SSID set
+ if (0 < ssid.trim().length()) {
scanResult =
new ScanResult(
- ssid, bssid, flags, level, freq, tsf);
+ ssid, bssid, flags, level, frequency);
mScanResultCache.put(key, scanResult);
}
- mScanResults.add(scanResult);
}
- bssid = null;
- level = 0;
- freq = 0;
- tsf = 0;
- flags = "";
- ssid = "";
+ } else {
+ loge("Misformatted scan result text with " +
+ result.length + " fields: " + line);
}
}
}
+
+ return scanResult;
+ }
+
+ /**
+ * scanResults input format
+ * 00:bb:cc:dd:cc:ee 2427 166 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net1
+ * 00:bb:cc:dd:cc:ff 2412 165 [WPA-EAP-TKIP][WPA2-EAP-CCMP] Net2
+ */
+ private void setScanResults(String scanResults) {
+ if (scanResults == null) {
+ return;
+ }
+
+ List<ScanResult> scanList = new ArrayList<ScanResult>();
+
+ int lineCount = 0;
+
+ int scanResultsLen = scanResults.length();
+ // Parse the result string, keeping in mind that the last line does
+ // not end with a newline.
+ for (int lineBeg = 0, lineEnd = 0; lineEnd <= scanResultsLen; ++lineEnd) {
+ if (lineEnd == scanResultsLen || scanResults.charAt(lineEnd) == '\n') {
+ ++lineCount;
+
+ if (lineCount == 1) {
+ lineBeg = lineEnd + 1;
+ continue;
+ }
+ if (lineEnd > lineBeg) {
+ String line = scanResults.substring(lineBeg, lineEnd);
+ ScanResult scanResult = parseScanResult(line);
+ if (scanResult != null) {
+ scanList.add(scanResult);
+ } else {
+ //TODO: hidden network handling
+ }
+ }
+ lineBeg = lineEnd + 1;
+ }
+ }
+
+ mScanResults = scanList;
}
/*
@@ -2805,7 +2827,7 @@
if (DBG) log(getName() + "\n");
mIsRunning = false;
updateBatteryWorkSource(null);
- mScanResults = new ArrayList<ScanResult>();
+ mScanResults = null;
if (mP2pSupported) mWifiP2pChannel.sendMessage(WifiStateMachine.CMD_DISABLE_P2P);
mContext.unregisterReceiver(mScreenReceiver);