summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt52
-rw-r--r--cmds/dumpstate/Android.mk5
-rw-r--r--cmds/dumpstate/dumpstate.c12
-rw-r--r--cmds/dumpstate/dumpstate.h4
-rw-r--r--core/java/android/app/ActivityManagerNative.java20
-rw-r--r--core/java/android/app/IActivityManager.java3
-rw-r--r--core/java/android/appwidget/AppWidgetHost.java4
-rw-r--r--core/java/android/appwidget/AppWidgetProviderInfo.java24
-rw-r--r--core/java/android/net/TrafficStats.java9
-rw-r--r--core/java/android/os/RecoverySystem.java15
-rw-r--r--core/java/android/provider/Settings.java8
-rw-r--r--core/java/android/provider/VoicemailContract.java87
-rw-r--r--core/java/android/view/Display.java1
-rw-r--r--core/java/android/view/HardwareRenderer.java96
-rw-r--r--core/java/android/view/View.java26
-rw-r--r--core/java/android/view/ViewGroup.java13
-rw-r--r--core/java/android/widget/GridLayout.java12
-rw-r--r--core/java/android/widget/TextView.java70
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java33
-rw-r--r--core/java/com/android/server/NetworkManagementSocketTagger.java8
-rw-r--r--core/res/AndroidManifest.xml17
-rw-r--r--core/res/res/layout-sw600dp/preference_list_content.xml1
-rw-r--r--core/res/res/values-land/dimens.xml2
-rw-r--r--core/res/res/values-sw600dp/dimens.xml9
-rw-r--r--core/res/res/values-w1024dp/dimens.xml23
-rw-r--r--core/res/res/values-w1280dp/dimens.xml1
-rwxr-xr-xcore/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--core/res/res/values/public.xml2
-rwxr-xr-xcore/res/res/values/strings.xml16
-rw-r--r--core/tests/coretests/src/android/util/JsonReaderTest.java2
-rw-r--r--data/fonts/DroidKufi-Bold.ttfbin0 -> 81220 bytes
-rw-r--r--data/fonts/DroidKufi-Regular.ttfbin0 -> 81224 bytes
-rw-r--r--data/fonts/DroidNaskh-Bold.ttfbin0 -> 383016 bytes
-rw-r--r--data/fonts/DroidNaskh-Regular.ttfbin0 -> 366760 bytes
-rw-r--r--data/fonts/DroidSansArabic.ttfbin35880 -> 0 bytes
-rw-r--r--data/fonts/fallback_fonts.xml7
-rw-r--r--data/fonts/fonts.mk3
-rw-r--r--docs/html/guide/practices/design/jni.jd36
-rw-r--r--include/gui/ISurfaceTexture.h8
-rw-r--r--include/gui/SurfaceTexture.h27
-rw-r--r--include/gui/SurfaceTextureClient.h14
-rw-r--r--libs/gui/ISurfaceTexture.cpp30
-rw-r--r--libs/gui/SurfaceTexture.cpp32
-rw-r--r--libs/gui/SurfaceTextureClient.cpp60
-rw-r--r--libs/hwui/OpenGLRenderer.cpp2
-rw-r--r--libs/rs/Android.mk2
-rw-r--r--libs/rs/driver/rsdBcc.cpp104
-rw-r--r--libs/rs/rsContext.cpp1
-rw-r--r--libs/rs/rsFBOCache.h1
-rw-r--r--libs/ui/FramebufferNativeWindow.cpp42
-rw-r--r--media/java/android/media/AudioManager.java21
-rw-r--r--media/java/android/media/AudioService.java6
-rw-r--r--media/libmedia/mediaplayer.cpp2
-rw-r--r--media/libstagefright/ACodec.cpp7
-rw-r--r--media/libstagefright/ESDS.cpp20
-rwxr-xr-xmedia/libstagefright/OMXCodec.cpp7
-rw-r--r--media/libstagefright/colorconversion/SoftwareRenderer.cpp5
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp5
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp35
-rw-r--r--native/android/native_window.cpp10
-rw-r--r--opengl/tests/gl2_copyTexImage/Android.mk19
-rw-r--r--opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp467
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java22
-rw-r--r--services/camera/libcameraservice/CameraService.cpp27
-rw-r--r--services/java/com/android/server/AppWidgetService.java6
-rw-r--r--services/java/com/android/server/ConnectivityService.java53
-rw-r--r--services/java/com/android/server/MasterClearReceiver.java6
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java28
-rw-r--r--services/java/com/android/server/am/ActivityStack.java6
-rw-r--r--services/java/com/android/server/pm/Settings.java29
-rw-r--r--services/surfaceflinger/Layer.cpp51
-rw-r--r--services/surfaceflinger/Layer.h4
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.cpp17
-rw-r--r--services/surfaceflinger/SurfaceTextureLayer.h3
-rw-r--r--services/surfaceflinger/Transform.cpp37
-rw-r--r--services/surfaceflinger/clz.h35
-rw-r--r--telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java5
-rw-r--r--tests/TileBenchmark/Android.mk32
-rw-r--r--tests/TileBenchmark/AndroidManifest.xml20
-rw-r--r--tests/TileBenchmark/res/drawable-hdpi/icon.pngbin0 -> 4147 bytes
-rw-r--r--tests/TileBenchmark/res/drawable-ldpi/icon.pngbin0 -> 1723 bytes
-rw-r--r--tests/TileBenchmark/res/drawable-mdpi/icon.pngbin0 -> 2574 bytes
-rw-r--r--tests/TileBenchmark/res/layout/main.xml53
-rw-r--r--tests/TileBenchmark/res/layout/playback.xml58
-rw-r--r--tests/TileBenchmark/res/values/colors.xml25
-rw-r--r--tests/TileBenchmark/res/values/strings.xml67
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java188
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java264
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java159
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java203
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java106
-rw-r--r--tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java32
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java27
-rw-r--r--tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java37
-rw-r--r--tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java13
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java6
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java1
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java18
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java13
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java2
101 files changed, 2815 insertions, 394 deletions
diff --git a/api/current.txt b/api/current.txt
index b462695..6984b07 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -82,6 +82,8 @@ package android {
field public static final java.lang.String READ_SMS = "android.permission.READ_SMS";
field public static final java.lang.String READ_SYNC_SETTINGS = "android.permission.READ_SYNC_SETTINGS";
field public static final java.lang.String READ_SYNC_STATS = "android.permission.READ_SYNC_STATS";
+ field public static final java.lang.String READ_WRITE_ALL_VOICEMAIL = "com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL";
+ field public static final java.lang.String READ_WRITE_OWN_VOICEMAIL = "com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL";
field public static final java.lang.String REBOOT = "android.permission.REBOOT";
field public static final java.lang.String RECEIVE_BOOT_COMPLETED = "android.permission.RECEIVE_BOOT_COMPLETED";
field public static final java.lang.String RECEIVE_MMS = "android.permission.RECEIVE_MMS";
@@ -673,6 +675,8 @@ package android {
field public static final int minHeight = 16843072; // 0x1010140
field public static final int minLevel = 16843185; // 0x10101b1
field public static final int minLines = 16843094; // 0x1010156
+ field public static final int minResizeHeight = 16843690; // 0x10103aa
+ field public static final int minResizeWidth = 16843689; // 0x10103a9
field public static final int minSdkVersion = 16843276; // 0x101020c
field public static final int minWidth = 16843071; // 0x101013f
field public static final int mode = 16843134; // 0x101017e
@@ -3929,6 +3933,8 @@ package android.appwidget {
field public int initialLayout;
field public java.lang.String label;
field public int minHeight;
+ field public int minResizeHeight;
+ field public int minResizeWidth;
field public int minWidth;
field public int previewImage;
field public android.content.ComponentName provider;
@@ -11287,6 +11293,7 @@ package android.net {
method public static long getMobileRxPackets();
method public static long getMobileTxBytes();
method public static long getMobileTxPackets();
+ method public static int getThreadStatsTag();
method public static long getTotalRxBytes();
method public static long getTotalRxPackets();
method public static long getTotalTxBytes();
@@ -11912,6 +11919,7 @@ package android.net.wifi {
field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
+ field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
@@ -14434,6 +14442,7 @@ package android.os {
public class RecoverySystem {
ctor public RecoverySystem();
method public static void installPackage(android.content.Context, java.io.File) throws java.io.IOException;
+ method public static void rebootWipeCache(android.content.Context) throws java.io.IOException;
method public static void rebootWipeUserData(android.content.Context) throws java.io.IOException;
method public static void verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File) throws java.security.GeneralSecurityException, java.io.IOException;
}
@@ -16916,6 +16925,49 @@ package android.provider {
field public static final java.lang.String _ID = "_id";
}
+ public class VoicemailContract {
+ field public static final java.lang.String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
+ field public static final java.lang.String AUTHORITY = "com.android.voicemail";
+ field public static final java.lang.String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
+ field public static final java.lang.String PARAM_KEY_SOURCE_PACKAGE = "source_package";
+ }
+
+ public static final class VoicemailContract.Status implements android.provider.BaseColumns {
+ method public static android.net.Uri buildSourceUri(java.lang.String);
+ field public static final java.lang.String CONFIGURATION_STATE = "configuration_state";
+ field public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2; // 0x2
+ field public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1; // 0x1
+ field public static final int CONFIGURATION_STATE_OK = 0; // 0x0
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String DATA_CHANNEL_STATE = "data_channel_state";
+ field public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+ field public static final int DATA_CHANNEL_STATE_OK = 0; // 0x0
+ field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
+ field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
+ field public static final java.lang.String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
+ field public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2; // 0x2
+ field public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1; // 0x1
+ field public static final int NOTIFICATION_CHANNEL_STATE_OK = 0; // 0x0
+ field public static final java.lang.String SETTINGS_URI = "settings_uri";
+ field public static final java.lang.String SOURCE_PACKAGE = "source_package";
+ field public static final java.lang.String VOICEMAIL_ACCESS_URI = "voicemail_access_uri";
+ }
+
+ public static final class VoicemailContract.Voicemails implements android.provider.BaseColumns {
+ method public static android.net.Uri buildSourceUri(java.lang.String);
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final java.lang.String DATE = "date";
+ field public static final java.lang.String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
+ field public static final java.lang.String DURATION = "duration";
+ field public static final java.lang.String HAS_CONTENT = "has_content";
+ field public static final java.lang.String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
+ field public static final java.lang.String MIME_TYPE = "mime_type";
+ 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 SOURCE_DATA = "source_data";
+ field public static final java.lang.String SOURCE_PACKAGE = "source_package";
+ }
+
}
package android.renderscript {
diff --git a/cmds/dumpstate/Android.mk b/cmds/dumpstate/Android.mk
index 56f1324..d602500 100644
--- a/cmds/dumpstate/Android.mk
+++ b/cmds/dumpstate/Android.mk
@@ -11,4 +11,9 @@ LOCAL_MODULE := dumpstate
LOCAL_SHARED_LIBRARIES := libcutils
+ifdef BOARD_LIB_DUMPSTATE
+LOCAL_STATIC_LIBRARIES := $(BOARD_LIB_DUMPSTATE)
+LOCAL_CFLAGS += -DBOARD_HAS_DUMPSTATE
+endif
+
include $(BUILD_EXECUTABLE)
diff --git a/cmds/dumpstate/dumpstate.c b/cmds/dumpstate/dumpstate.c
index 42c35af..4926db2 100644
--- a/cmds/dumpstate/dumpstate.c
+++ b/cmds/dumpstate/dumpstate.c
@@ -197,6 +197,15 @@ static void dumpstate() {
dump_file(NULL, "/sys/class/leds/lcd-backlight/registers");
printf("\n");
+#ifdef BOARD_HAS_DUMPSTATE
+ printf("========================================================\n");
+ printf("== Board\n");
+ printf("========================================================\n");
+
+ dumpstate_board();
+ printf("\n");
+#endif
+
printf("========================================================\n");
printf("== Android Framework Services\n");
printf("========================================================\n");
@@ -218,6 +227,9 @@ static void dumpstate() {
run_command("APP SERVICES", 30, "dumpsys", "activity", "service", "all", NULL);
+ printf("========================================================\n");
+ printf("== dumpstate: done\n");
+ printf("========================================================\n");
}
static void usage() {
diff --git a/cmds/dumpstate/dumpstate.h b/cmds/dumpstate/dumpstate.h
index 83b1d11..597ab1f 100644
--- a/cmds/dumpstate/dumpstate.h
+++ b/cmds/dumpstate/dumpstate.h
@@ -19,6 +19,7 @@
#include <time.h>
#include <unistd.h>
+#include <stdio.h>
/* prints the contents of a file */
int dump_file(const char *title, const char* path);
@@ -47,4 +48,7 @@ void show_wchan(int pid, const char *name);
/* Play a sound via Stagefright */
void play_sound(const char* path);
+/* Implemented by libdumpstate_board to dump board-specific info */
+void dumpstate_board();
+
#endif /* _DUMPSTATE_H_ */
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index fdf4a3a..2a731a3 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1514,6 +1514,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ Configuration config = Configuration.CREATOR.createFromParcel(data);
+ updatePersistentConfiguration(config);
+ reply.writeNoException();
+ return true;
+ }
+
}
return super.onTransact(code, data, reply, flags);
@@ -3410,5 +3418,17 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
+ public void updatePersistentConfiguration(Configuration values) throws RemoteException
+ {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ values.writeToParcel(data, 0);
+ mRemote.transact(UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
private IBinder mRemote;
}
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 9e20764..93c821c 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -363,6 +363,8 @@ public interface IActivityManager extends IInterface {
public boolean isIntentSenderTargetedToPackage(IIntentSender sender) throws RemoteException;
+ public void updatePersistentConfiguration(Configuration values) throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -590,4 +592,5 @@ public interface IActivityManager extends IInterface {
int REGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+132;
int UNREGISTER_PROCESS_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+133;
int IS_INTENT_SENDER_TARGETED_TO_PACKAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+134;
+ int UPDATE_PERSISTENT_CONFIGURATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+135;
}
diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java
index 8204a4f..08bc0ac 100644
--- a/core/java/android/appwidget/AppWidgetHost.java
+++ b/core/java/android/appwidget/AppWidgetHost.java
@@ -261,6 +261,10 @@ public class AppWidgetHost {
TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);
appWidget.minHeight =
TypedValue.complexToDimensionPixelSize(appWidget.minHeight, mDisplayMetrics);
+ appWidget.minResizeWidth =
+ TypedValue.complexToDimensionPixelSize(appWidget.minResizeWidth, mDisplayMetrics);
+ appWidget.minResizeHeight =
+ TypedValue.complexToDimensionPixelSize(appWidget.minResizeHeight, mDisplayMetrics);
synchronized (mViews) {
v = mViews.get(appWidgetId);
diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java
index b46802e..b8c5b02 100644
--- a/core/java/android/appwidget/AppWidgetProviderInfo.java
+++ b/core/java/android/appwidget/AppWidgetProviderInfo.java
@@ -54,7 +54,8 @@ public class AppWidgetProviderInfo implements Parcelable {
public ComponentName provider;
/**
- * Minimum width of the AppWidget, in dp.
+ * The default height of the widget when added to a host, in dp. The widget will get
+ * at least this width, and will often be given more, depending on the host.
*
* <p>This field corresponds to the <code>android:minWidth</code> attribute in
* the AppWidget meta-data file.
@@ -62,7 +63,8 @@ public class AppWidgetProviderInfo implements Parcelable {
public int minWidth;
/**
- * Minimum height of the AppWidget, in dp.
+ * The default height of the widget when added to a host, in dp. The widget will get
+ * at least this height, and will often be given more, depending on the host.
*
* <p>This field corresponds to the <code>android:minHeight</code> attribute in
* the AppWidget meta-data file.
@@ -70,6 +72,24 @@ public class AppWidgetProviderInfo implements Parcelable {
public int minHeight;
/**
+ * Minimum width (in dp) which the widget can be resized to. This field has no effect if it
+ * is greater than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}).
+ *
+ * <p>This field corresponds to the <code>android:minResizeWidth</code> attribute in
+ * the AppWidget meta-data file.
+ */
+ public int minResizeWidth;
+
+ /**
+ * Minimum height (in dp) which the widget can be resized to. This field has no effect if it
+ * is greater than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}).
+ *
+ * <p>This field corresponds to the <code>android:minResizeHeight</code> attribute in
+ * the AppWidget meta-data file.
+ */
+ public int minResizeHeight;
+
+ /**
* How often, in milliseconds, that this AppWidget wants to be updated.
* The AppWidget manager may place a limit on how often a AppWidget is updated.
*
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 2b59dba..e054930 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -97,6 +97,15 @@ public class TrafficStats {
}
/**
+ * Get the active tag used when accounting {@link Socket} traffic originating
+ * from the current thread. Only one active tag per thread is supported.
+ * {@link #tagSocket(Socket)}.
+ */
+ public static int getThreadStatsTag() {
+ return NetworkManagementSocketTagger.getThreadSocketStatsTag();
+ }
+
+ /**
* @deprecated unsupported, will eventually be removed
*/
@Deprecated
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index ae605fb..73e8d98 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -357,20 +357,11 @@ public class RecoverySystem {
}
/**
- * Reboot into the recovery system to wipe the /data partition and toggle
- * Encrypted File Systems on/off.
- * @param extras to add to the RECOVERY_COMPLETED intent after rebooting.
+ * Reboot into the recovery system to wipe the /cache partition.
* @throws IOException if something goes wrong.
- *
- * @hide
*/
- public static void rebootToggleEFS(Context context, boolean efsEnabled)
- throws IOException {
- if (efsEnabled) {
- bootCommand(context, "--set_encrypted_filesystem=on");
- } else {
- bootCommand(context, "--set_encrypted_filesystem=off");
- }
+ public static void rebootWipeCache(Context context) throws IOException {
+ bootCommand(context, "--wipe_cache");
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 34699e2..ad32047 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1045,6 +1045,14 @@ public final class Settings {
}
/**
+ * @hide Erase the fields in the Configuration that should be applied
+ * by the settings.
+ */
+ public static void clearConfiguration(Configuration inoutConfig) {
+ inoutConfig.fontScale = 0;
+ }
+
+ /**
* Convenience function to write a batch of configuration-related
* settings from a {@link Configuration} object.
*
diff --git a/core/java/android/provider/VoicemailContract.java b/core/java/android/provider/VoicemailContract.java
index d0712d5..2ad7395 100644
--- a/core/java/android/provider/VoicemailContract.java
+++ b/core/java/android/provider/VoicemailContract.java
@@ -16,6 +16,9 @@
package android.provider;
+import android.Manifest;
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
import android.content.Intent;
import android.database.ContentObserver;
import android.net.Uri;
@@ -25,11 +28,26 @@ import android.provider.CallLog.Calls;
* The contract between the voicemail provider and applications. Contains
* definitions for the supported URIs and columns.
*
+ * <P>The content providers exposes two tables through this interface:
+ * <ul>
+ * <li> Voicemails table: This stores the actual voicemail records. The
+ * columns and URIs for accessing this table are defined by the
+ * {@link Voicemails} class.
+ * </li>
+ * <li> Status table: This provides a way for the voicemail source application
+ * to convey its current state to the system. The columns and URIS for
+ * accessing this table are defined by the {@link Status} class.
+ * </li>
+ * </ul>
+ *
+ * <P> The minimum permission needed to access this content provider is
+ * {@link Manifest.permission#READ_WRITE_OWN_VOICEMAIL}
+ *
* <P>Voicemails are inserted by what is called as a "voicemail source"
* application, which is responsible for syncing voicemail data between a remote
* server and the local voicemail content provider. "voicemail source"
- * application should use the source specific {@link #CONTENT_URI_SOURCE} URI
- * to insert and retrieve voicemails.
+ * application should always set the {@link #PARAM_KEY_SOURCE_PACKAGE} in the
+ * URI to identify its package.
*
* <P>In addition to the {@link ContentObserver} notifications the voicemail
* provider also generates broadcast intents to notify change for applications
@@ -43,9 +61,7 @@ import android.provider.CallLog.Calls;
* made into the database, including new voicemail.
* </li>
* </ul>
- * @hide
*/
-// TODO: unhide when the API is approved by android-api-council
public class VoicemailContract {
/** Not instantiable. */
private VoicemailContract() {
@@ -59,18 +75,18 @@ public class VoicemailContract {
*/
public static final String PARAM_KEY_SOURCE_PACKAGE = "source_package";
- // TODO: Move ACTION_NEW_VOICEMAIL to the Intent class.
/** Broadcast intent when a new voicemail record is inserted. */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_NEW_VOICEMAIL = "android.intent.action.NEW_VOICEMAIL";
/**
- * Extra included in {@value Intent#ACTION_PROVIDER_CHANGED} and
- * {@value #ACTION_NEW_VOICEMAIL} broadcast intents to indicate if the receiving
- * package made this change.
+ * Extra included in {@link Intent#ACTION_PROVIDER_CHANGED} broadcast intents to indicate if the
+ * receiving package made this change.
*/
public static final String EXTRA_SELF_CHANGE = "com.android.voicemail.extra.SELF_CHANGE";
/**
* Name of the source package field, which must be same across all voicemail related tables.
+ * This is an internal field.
* @hide
*/
public static final String SOURCE_PACKAGE_FIELD = "source_package";
@@ -85,9 +101,12 @@ public class VoicemailContract {
public static final Uri CONTENT_URI =
Uri.parse("content://" + AUTHORITY + "/voicemail");
- /** The mime type for a collection of voicemails. */
+ /** The MIME type for a collection of voicemails. */
public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemails";
+ /** The MIME type for a single voicemail. */
+ public static final String ITEM_TYPE = "vnd.android.cursor.item/voicemail";
+
/**
* Phone number of the voicemail sender.
* <P>Type: TEXT</P>
@@ -109,17 +128,27 @@ public class VoicemailContract {
*/
public static final String NEW = Calls.NEW;
/**
- * The mail box state of the voicemail.
+ * The mail box state of the voicemail. This field is currently not used by the system.
* <P> Possible values: {@link #STATE_INBOX}, {@link #STATE_DELETED},
* {@link #STATE_UNDELETED}.
* <P>Type: INTEGER</P>
+ * @hide
*/
public static final String STATE = "state";
- /** Value of {@link #STATE} when the voicemail is in inbox. */
+ /**
+ * Value of {@link #STATE} when the voicemail is in inbox.
+ * @hide
+ */
public static int STATE_INBOX = 0;
- /** Value of {@link #STATE} when the voicemail has been marked as deleted. */
+ /**
+ * Value of {@link #STATE} when the voicemail has been marked as deleted.
+ * @hide
+ */
public static int STATE_DELETED = 1;
- /** Value of {@link #STATE} when the voicemail has marked as undeleted. */
+ /**
+ * Value of {@link #STATE} when the voicemail has marked as undeleted.
+ * @hide
+ */
public static int STATE_UNDELETED = 2;
/**
* Package name of the source application that inserted the voicemail.
@@ -166,9 +195,9 @@ public class VoicemailContract {
public static final class Status implements BaseColumns {
/** URI to insert/retrieve status of voicemail source. */
public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/status");
- /** The mime type for a collection of voicemail source statuses. */
+ /** The MIME type for a collection of voicemail source statuses. */
public static final String DIR_TYPE = "vnd.android.cursor.dir/voicemail.source.status";
- /** The mime type for a collection of voicemails. */
+ /** The MIME type for a single voicemail source status entry. */
public static final String ITEM_TYPE = "vnd.android.cursor.item/voicemail.source.status";
/** Not instantiable. */
@@ -201,10 +230,17 @@ public class VoicemailContract {
* <P>Type: INTEGER</P>
*/
public static final String CONFIGURATION_STATE = "configuration_state";
+ /** Value of {@link #CONFIGURATION_STATE} to indicate an all OK configuration status. */
public static final int CONFIGURATION_STATE_OK = 0;
+ /**
+ * Value of {@link #CONFIGURATION_STATE} to indicate the visual voicemail is not
+ * yet configured on this device.
+ */
public static final int CONFIGURATION_STATE_NOT_CONFIGURED = 1;
/**
- * This state must be used when the source has verified that the current user can be
+ * Value of {@link #CONFIGURATION_STATE} to indicate the visual voicemail is not
+ * yet configured on this device but can be configured by the user.
+ * <p> This state must be used when the source has verified that the current user can be
* upgraded to visual voicemail and would like to show a set up invitation message.
*/
public static final int CONFIGURATION_STATE_CAN_BE_CONFIGURED = 2;
@@ -218,7 +254,14 @@ public class VoicemailContract {
* <P>Type: INTEGER</P>
*/
public static final String DATA_CHANNEL_STATE = "data_channel_state";
+ /**
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel is working fine.
+ */
public static final int DATA_CHANNEL_STATE_OK = 0;
+ /**
+ * Value of {@link #DATA_CHANNEL_STATE} to indicate that data channel connection is not
+ * working.
+ */
public static final int DATA_CHANNEL_STATE_NO_CONNECTION = 1;
/**
* The notification channel state of the voicemail source. This is the channel through which
@@ -231,10 +274,20 @@ public class VoicemailContract {
* <P>Type: INTEGER</P>
*/
public static final String NOTIFICATION_CHANNEL_STATE = "notification_channel_state";
+ /**
+ * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel is
+ * working fine.
+ */
public static final int NOTIFICATION_CHANNEL_STATE_OK = 0;
+ /**
+ * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that the notification channel
+ * connection is not working.
+ */
public static final int NOTIFICATION_CHANNEL_STATE_NO_CONNECTION = 1;
/**
- * Use this state when the notification can only tell that there are pending messages on
+ * Value of {@link #NOTIFICATION_CHANNEL_STATE} to indicate that there are messages waiting
+ * on the server but the details are not known.
+ * <p> Use this state when the notification can only tell that there are pending messages on
* the server but no details of the sender/time etc are known.
*/
public static final int NOTIFICATION_CHANNEL_STATE_MESSAGE_WAITING = 2;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 2be5a49..5ab2024 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -118,6 +118,7 @@ public class Display {
} else {
// This is just for boot-strapping, initializing the
// system process before the window manager is up.
+ outSize.x = getRealWidth();
outSize.y = getRealHeight();
}
if (DEBUG_COMPAT && doCompat) Slog.v(TAG, "Returning display size: " + outSize);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 9a2564f..b865b50 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -325,12 +325,15 @@ public abstract class HardwareRenderer {
private static final int SURFACE_STATE_SUCCESS = 1;
private static final int SURFACE_STATE_UPDATED = 2;
- static EGLContext sEglContext;
static EGL10 sEgl;
static EGLDisplay sEglDisplay;
static EGLConfig sEglConfig;
+ static final Object[] sEglLock = new Object[0];
- private static Thread sEglThread;
+ static final ThreadLocal<EGLContext> sEglContextStorage = new ThreadLocal<EGLContext>();
+
+ EGLContext mEglContext;
+ Thread mEglThread;
EGLSurface mEglSurface;
@@ -355,7 +358,7 @@ public abstract class HardwareRenderer {
final boolean mTranslucent;
private boolean mDestroyed;
-
+
private final Rect mRedrawClip = new Rect();
GlRenderer(int glVersion, boolean translucent) {
@@ -487,45 +490,48 @@ public abstract class HardwareRenderer {
abstract GLES20Canvas createCanvas();
void initializeEgl() {
- if (sEglContext != null) return;
-
- sEglThread = Thread.currentThread();
- sEgl = (EGL10) EGLContext.getEGL();
-
- // Get to the default display.
- sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-
- if (sEglDisplay == EGL10.EGL_NO_DISPLAY) {
- throw new RuntimeException("eglGetDisplay failed "
- + getEGLErrorString(sEgl.eglGetError()));
- }
-
- // We can now initialize EGL for that display
- int[] version = new int[2];
- if (!sEgl.eglInitialize(sEglDisplay, version)) {
- throw new RuntimeException("eglInitialize failed " +
- getEGLErrorString(sEgl.eglGetError()));
- }
-
- sEglConfig = chooseEglConfig();
- if (sEglConfig == null) {
- // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
- if (sDirtyRegions) {
- sDirtyRegions = false;
+ synchronized (sEglLock) {
+ if (sEgl == null && sEglConfig == null) {
+ sEgl = (EGL10) EGLContext.getEGL();
+
+ // Get to the default display.
+ sEglDisplay = sEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+
+ if (sEglDisplay == EGL10.EGL_NO_DISPLAY) {
+ throw new RuntimeException("eglGetDisplay failed "
+ + getEGLErrorString(sEgl.eglGetError()));
+ }
+
+ // We can now initialize EGL for that display
+ int[] version = new int[2];
+ if (!sEgl.eglInitialize(sEglDisplay, version)) {
+ throw new RuntimeException("eglInitialize failed " +
+ getEGLErrorString(sEgl.eglGetError()));
+ }
+
sEglConfig = chooseEglConfig();
if (sEglConfig == null) {
- throw new RuntimeException("eglConfig not initialized");
+ // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
+ if (sDirtyRegions) {
+ sDirtyRegions = false;
+ sEglConfig = chooseEglConfig();
+ if (sEglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized");
+ }
+ } else {
+ throw new RuntimeException("eglConfig not initialized");
+ }
}
- } else {
- throw new RuntimeException("eglConfig not initialized");
}
}
-
- /*
- * Create an EGL context. We want to do this as rarely as we can, because an
- * EGL context is a somewhat heavy object.
- */
- sEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
+
+ mEglContext = sEglContextStorage.get();
+ mEglThread = Thread.currentThread();
+
+ if (mEglContext == null) {
+ mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
+ sEglContextStorage.set(mEglContext);
+ }
}
private EGLConfig chooseEglConfig() {
@@ -554,7 +560,7 @@ public abstract class HardwareRenderer {
if (sEglConfig == null) {
throw new RuntimeException("eglConfig not initialized");
}
- if (Thread.currentThread() != sEglThread) {
+ if (Thread.currentThread() != mEglThread) {
throw new IllegalStateException("HardwareRenderer cannot be used "
+ "from multiple threads");
}
@@ -590,7 +596,7 @@ public abstract class HardwareRenderer {
* Before we can issue GL commands, we need to make sure
* the context is current and bound to a surface.
*/
- if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
+ if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
throw new Surface.OutOfResourcesException("eglMakeCurrent failed "
+ getEGLErrorString(sEgl.eglGetError()));
}
@@ -611,7 +617,7 @@ public abstract class HardwareRenderer {
mDirtyRegionsEnabled = GLES20Canvas.isBackBufferPreserved();
}
- return sEglContext.getGL();
+ return mEglContext.getGL();
}
EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
@@ -752,22 +758,22 @@ public abstract class HardwareRenderer {
}
/**
- * Ensures the currnet EGL context is the one we expect.
+ * Ensures the current EGL context is the one we expect.
*
* @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
* {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
* {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
*/
private int checkCurrent() {
- if (sEglThread != Thread.currentThread()) {
+ if (mEglThread != Thread.currentThread()) {
throw new IllegalStateException("Hardware acceleration can only be used with a " +
- "single UI thread.\nOriginal thread: " + sEglThread + "\n" +
+ "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
"Current thread: " + Thread.currentThread());
}
- if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
+ if (!mEglContext.equals(sEgl.eglGetCurrentContext()) ||
!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
- if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
+ if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
fallback(true);
Log.e(LOG_TAG, "eglMakeCurrent failed " +
getEGLErrorString(sEgl.eglGetError()));
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 59cb216..ff5fa7f 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -10317,6 +10317,26 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
}
/**
+ * @hide
+ * @param offsetRequired
+ */
+ protected int getFadeTop(boolean offsetRequired) {
+ int top = mPaddingTop;
+ if (offsetRequired) top += getTopPaddingOffset();
+ return top;
+ }
+
+ /**
+ * @hide
+ * @param offsetRequired
+ */
+ protected int getFadeHeight(boolean offsetRequired) {
+ int padding = mPaddingTop;
+ if (offsetRequired) padding += getTopPaddingOffset();
+ return mBottom - mTop - mPaddingBottom - padding;
+ }
+
+ /**
* <p>Indicates whether this view is attached to an hardware accelerated
* window or not.</p>
*
@@ -10427,18 +10447,16 @@ public class View implements Drawable.Callback2, KeyEvent.Callback, Accessibilit
// Step 2, save the canvas' layers
int paddingLeft = mPaddingLeft;
- int paddingTop = mPaddingTop;
final boolean offsetRequired = isPaddingOffsetRequired();
if (offsetRequired) {
paddingLeft += getLeftPaddingOffset();
- paddingTop += getTopPaddingOffset();
}
int left = mScrollX + paddingLeft;
int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
- int top = mScrollY + paddingTop;
- int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;
+ int top = mScrollY + getFadeTop(offsetRequired);
+ int bottom = top + getFadeHeight(offsetRequired);
if (offsetRequired) {
right += getRightPaddingOffset();
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index a6c158d..54fee3c 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -843,7 +843,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @param child
* @param visibility
*/
- void onChildVisibilityChanged(View child, int visibility) {
+ protected void onChildVisibilityChanged(View child, int visibility) {
if (mTransition != null) {
if (visibility == VISIBLE) {
mTransition.showChild(this, child);
@@ -3964,7 +3964,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final int left = mLeft;
final int top = mTop;
- if (dirty.intersect(0, 0, mRight - left, mBottom - top) ||
+ if ((mGroupFlags & FLAG_CLIP_CHILDREN) != FLAG_CLIP_CHILDREN ||
+ dirty.intersect(0, 0, mRight - left, mBottom - top) ||
(mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
@@ -3982,8 +3983,12 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
location[CHILD_LEFT_INDEX] = mLeft;
location[CHILD_TOP_INDEX] = mTop;
-
- dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
+ if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
+ dirty.set(0, 0, mRight - mLeft, mBottom - mTop);
+ } else {
+ // in case the dirty rect extends outside the bounds of this container
+ dirty.union(0, 0, mRight - mLeft, mBottom - mTop);
+ }
if (mLayerType != LAYER_TYPE_NONE) {
mLocalDirtyRect.union(dirty);
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index 46fe407..5747fd3 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -775,6 +775,18 @@ public class GridLayout extends ViewGroup {
invalidateStructure();
}
+ /**
+ * We need to call invalidateStructure() when a child's GONE flag changes state.
+ * This implementation is a catch-all, invalidating on any change in the visibility flags.
+ *
+ * @hide
+ */
+ @Override
+ protected void onChildVisibilityChanged(View child, int visibility) {
+ super.onChildVisibilityChanged(child, visibility);
+ invalidateStructure();
+ }
+
// Measurement
private boolean isGone(View c) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 66a07d3..b116f0f 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -117,12 +117,12 @@ import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewRootImpl;
import android.view.ViewConfiguration;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
+import android.view.ViewRootImpl;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
@@ -362,7 +362,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
INHERIT, GRAVITY, TEXT_START, TEXT_END, CENTER, VIEW_START, VIEW_END;
}
- private boolean bResolvedDrawables = false;
+ private boolean mResolvedDrawables = false;
/*
* Kick-start the font cache for the zygote process (to pay the cost of
@@ -3424,7 +3424,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mHint;
}
- private boolean isMultilineInputType(int type) {
+ private static boolean isMultilineInputType(int type) {
return (type & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE)) ==
(EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
}
@@ -3500,7 +3500,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return mTransformation instanceof PasswordTransformationMethod;
}
- private boolean isPasswordInputType(int inputType) {
+ private static boolean isPasswordInputType(int inputType) {
final int variation =
inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
return variation
@@ -3511,7 +3511,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
== (EditorInfo.TYPE_CLASS_NUMBER | EditorInfo.TYPE_NUMBER_VARIATION_PASSWORD);
}
- private boolean isVisiblePasswordInputType(int inputType) {
+ private static boolean isVisiblePasswordInputType(int inputType) {
final int variation =
inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
return variation
@@ -5062,6 +5062,33 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return getExtendedPaddingTop() + voffset + mLayout.getLineBaseline(0);
}
+ /**
+ * @hide
+ * @param offsetRequired
+ */
+ @Override
+ protected int getFadeTop(boolean offsetRequired) {
+ if (mLayout == null) return 0;
+
+ int voffset = 0;
+ if ((mGravity & Gravity.VERTICAL_GRAVITY_MASK) != Gravity.TOP) {
+ voffset = getVerticalOffset(true);
+ }
+
+ if (offsetRequired) voffset += getTopPaddingOffset();
+
+ return getExtendedPaddingTop() + voffset;
+ }
+
+ /**
+ * @hide
+ * @param offsetRequired
+ */
+ @Override
+ protected int getFadeHeight(boolean offsetRequired) {
+ return mLayout != null ? mLayout.getHeight() : 0;
+ }
+
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
int which = doKeyDown(keyCode, event, null);
@@ -7592,7 +7619,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// mode (if any) as soon as this TextView is recycled.
stopSelectionActionMode();
}
-
+
@Override
public void onFinishTemporaryDetach() {
super.onFinishTemporaryDetach();
@@ -7600,7 +7627,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// usually because this instance is an editable field in a list
if (!mDispatchTemporaryDetach) mTemporaryDetach = false;
}
-
+
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
if (mTemporaryDetach) {
@@ -9174,16 +9201,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* Paste actions, depending on what this View supports.
*
* A custom implementation can add new entries in the default menu in its
- * {@link ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The default actions
- * can also be removed from the menu using {@link Menu#removeItem(int)} and passing
- * {@link android.R.id#selectAll}, {@link android.R.id#cut}, {@link android.R.id#copy} or
- * {@link android.R.id#paste} ids as parameters.
+ * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
+ * default actions can also be removed from the menu using {@link Menu#removeItem(int)} and
+ * passing {@link android.R.id#selectAll}, {@link android.R.id#cut}, {@link android.R.id#copy}
+ * or {@link android.R.id#paste} ids as parameters.
*
- * Returning false from {@link ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will
- * prevent the action mode from being started.
+ * Returning false from
+ * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
+ * the action mode from being started.
*
* Action click events should be handled by the custom implementation of
- * {@link ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
+ * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
*
* Note that text selection mode is not started when a TextView receives focus and the
* {@link android.R.attr#selectAllOnFocus} flag has been set. The content is highlighted in
@@ -9739,9 +9767,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mLastParentX = mTempCoords[0];
mLastParentY = mTempCoords[1];
}
- }
- onHandleMoved();
+ onHandleMoved();
+ }
if (isPositionVisible()) {
mContainer.update(mContainerPositionX, mContainerPositionY,
@@ -10184,7 +10212,6 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mPreviousTapPositionX = x;
mPreviousTapPositionY = y;
-
break;
case MotionEvent.ACTION_POINTER_DOWN:
@@ -10500,6 +10527,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
mTextDir = TextDirectionHeuristics.RTL;
break;
}
+
}
/**
@@ -10511,7 +10539,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
*/
protected void resolveDrawables() {
// No need to resolve twice
- if (bResolvedDrawables) {
+ if (mResolvedDrawables) {
return;
}
// No drawable to resolve
@@ -10520,7 +10548,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
// No relative drawable to resolve
if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
- bResolvedDrawables = true;
+ mResolvedDrawables = true;
return;
}
@@ -10557,11 +10585,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
break;
}
- bResolvedDrawables = true;
+ mResolvedDrawables = true;
}
protected void resetResolvedDrawables() {
- bResolvedDrawables = false;
+ mResolvedDrawables = false;
}
@ViewDebug.ExportedProperty(category = "text")
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index f0a9441..95f1f98 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -76,7 +76,9 @@ public class ActionBarImpl extends ActionBar {
private TabImpl mSelectedTab;
private int mSavedTabPosition = INVALID_POSITION;
- private ActionMode mActionMode;
+ ActionModeImpl mActionMode;
+ ActionMode mDeferredDestroyActionMode;
+ ActionMode.Callback mDeferredModeDestroyCallback;
private boolean mLastMenuVisibility;
private ArrayList<OnMenuVisibilityListener> mMenuVisibilityListeners =
@@ -104,10 +106,12 @@ public class ActionBarImpl extends ActionBar {
public void onAnimationEnd(Animator animation) {
if (mContentView != null) {
mContentView.setTranslationY(0);
+ mContainerView.setTranslationY(0);
}
mContainerView.setVisibility(View.GONE);
mContainerView.setTransitioning(false);
mCurrentShowAnim = null;
+ completeDeferredDestroyActionMode();
}
};
@@ -207,6 +211,14 @@ public class ActionBarImpl extends ActionBar {
mTabScrollView = tabScroller;
}
+ void completeDeferredDestroyActionMode() {
+ if (mDeferredModeDestroyCallback != null) {
+ mDeferredModeDestroyCallback.onDestroyActionMode(mDeferredDestroyActionMode);
+ mDeferredDestroyActionMode = null;
+ mDeferredModeDestroyCallback = null;
+ }
+ }
+
/**
* Enables or disables animation between show/hide states.
* If animation is disabled using this method, animations in progress
@@ -357,14 +369,16 @@ public class ActionBarImpl extends ActionBar {
}
public ActionMode startActionMode(ActionMode.Callback callback) {
+ boolean wasHidden = false;
if (mActionMode != null) {
+ wasHidden = mWasHiddenBeforeMode;
mActionMode.finish();
}
mContextView.killMode();
ActionModeImpl mode = new ActionModeImpl(callback);
if (mode.dispatchOnCreate()) {
- mWasHiddenBeforeMode = !isShowing();
+ mWasHiddenBeforeMode = !isShowing() || wasHidden;
mode.invalidate();
mContextView.initForMode(mode);
animateToMode(true);
@@ -577,7 +591,9 @@ public class ActionBarImpl extends ActionBar {
}
void animateToMode(boolean toActionMode) {
- show(false);
+ if (toActionMode) {
+ show(false);
+ }
if (mCurrentModeAnim != null) {
mCurrentModeAnim.end();
}
@@ -621,7 +637,16 @@ public class ActionBarImpl extends ActionBar {
return;
}
- mCallback.onDestroyActionMode(this);
+ // If we were hidden before the mode was shown, defer the onDestroy
+ // callback until the animation is finished and associated relayout
+ // is about to happen. This lets apps better anticipate visibility
+ // and layout behavior.
+ if (mWasHiddenBeforeMode) {
+ mDeferredDestroyActionMode = this;
+ mDeferredModeDestroyCallback = mCallback;
+ } else {
+ mCallback.onDestroyActionMode(this);
+ }
mCallback = null;
animateToMode(false);
diff --git a/core/java/com/android/server/NetworkManagementSocketTagger.java b/core/java/com/android/server/NetworkManagementSocketTagger.java
index c446cfb..59bef92 100644
--- a/core/java/com/android/server/NetworkManagementSocketTagger.java
+++ b/core/java/com/android/server/NetworkManagementSocketTagger.java
@@ -18,8 +18,8 @@ package com.android.server;
import android.os.SystemProperties;
import android.util.Log;
-
import dalvik.system.SocketTagger;
+import libcore.io.IoUtils;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -28,8 +28,6 @@ import java.math.BigInteger;
import java.net.SocketException;
import java.nio.charset.Charsets;
-import libcore.io.IoUtils;
-
/**
* Assigns tags to sockets for traffic stats.
*/
@@ -59,6 +57,10 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
threadSocketTags.get().statsTag = tag;
}
+ public static int getThreadSocketStatsTag() {
+ return threadSocketTags.get().statsTag;
+ }
+
public static void setThreadSocketStatsUid(int uid) {
threadSocketTags.get().statsUid = uid;
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0397dfa..290f049 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -292,6 +292,23 @@
android:description="@string/permdesc_setAlarm"
android:protectionLevel="normal" />
+ <!-- Allows an application to read/write the voicemails owned by its own
+ package. -->
+ <permission android:name="com.android.voicemail.permission.READ_WRITE_OWN_VOICEMAIL"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:protectionLevel="dangerous"
+ android:label="@string/permlab_readWriteOwnVoicemail"
+ android:description="@string/permdesc_readWriteOwnVoicemail" />
+
+ <!-- Allows an application to read/write all voicemails. In order to be able
+ access all voicemails, this permission is needed in *addition* to
+ READ_WRITE_OWN_VOICEMAIL. -->
+ <permission android:name="com.android.voicemail.permission.READ_WRITE_ALL_VOICEMAIL"
+ android:permissionGroup="android.permission-group.PERSONAL_INFO"
+ android:protectionLevel="signature"
+ android:label="@string/permlab_readWriteAllVoicemail"
+ android:description="@string/permdesc_readWriteAllVoicemail" />
+
<!-- ======================================= -->
<!-- Permissions for accessing location info -->
<!-- ======================================= -->
diff --git a/core/res/res/layout-sw600dp/preference_list_content.xml b/core/res/res/layout-sw600dp/preference_list_content.xml
index a5320a7..5b67d71 100644
--- a/core/res/res/layout-sw600dp/preference_list_content.xml
+++ b/core/res/res/layout-sw600dp/preference_list_content.xml
@@ -46,7 +46,6 @@
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp"
-
android:drawSelectorOnTop="false"
android:cacheColorHint="@android:color/transparent"
android:listPreferredItemHeight="48dp"
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index ec2313c..388eb38 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -25,8 +25,6 @@
<dimen name="password_keyboard_key_height_numeric">60dip</dimen>
<!-- Default correction for the space key in the password keyboard -->
<dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
- <dimen name="preference_screen_side_margin">16dp</dimen>
- <dimen name="preference_screen_side_margin_negative">-20dp</dimen>
<dimen name="preference_widget_width">72dp</dimen>
<!-- Default height of an action bar. -->
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 17bf561..553632b 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -45,6 +45,13 @@
<dimen name="keyguard_pattern_unlock_status_line_font_size">14sp</dimen>
<!-- Preference activity, vertical padding for the header list -->
- <dimen name="reference_screen_header_vertical_padding">16dp</dimen>
+ <dimen name="preference_screen_header_vertical_padding">16dp</dimen>
+
+ <!-- Reduce the margin when using dual pane -->
+ <!-- Preference activity side margins -->
+ <dimen name="preference_screen_side_margin">0dp</dimen>
+ <!-- Preference activity side margins negative-->
+ <dimen name="preference_screen_side_margin_negative">-4dp</dimen>
+
</resources>
diff --git a/core/res/res/values-w1024dp/dimens.xml b/core/res/res/values-w1024dp/dimens.xml
new file mode 100644
index 0000000..4d6a4da
--- /dev/null
+++ b/core/res/res/values-w1024dp/dimens.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <!-- Increase size (used to be 0 for dual pane -->
+ <!-- Preference activity side margins -->
+ <dimen name="preference_screen_side_margin">48dp</dimen>
+ <!-- Preference activity side margins negative-->
+ <dimen name="preference_screen_side_margin_negative">-52dp</dimen>
+</resources>
diff --git a/core/res/res/values-w1280dp/dimens.xml b/core/res/res/values-w1280dp/dimens.xml
index e67b3a9..28aea55 100644
--- a/core/res/res/values-w1280dp/dimens.xml
+++ b/core/res/res/values-w1280dp/dimens.xml
@@ -18,6 +18,7 @@
-->
<resources>
<dimen name="preference_screen_side_margin">96dp</dimen>
+ <!-- Compensate for double margin : preference_screen_side_margin + 4 (frame background shadow) = -preference_screen_side_margin_negative -->
<dimen name="preference_screen_side_margin_negative">-100dp</dimen>
<dimen name="preference_widget_width">64dp</dimen>
<!-- Preference fragment padding, bottom -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d0361ca..082284a 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -4913,6 +4913,10 @@
<attr name="minWidth"/>
<!-- Minimum height of the AppWidget. -->
<attr name="minHeight"/>
+ <!-- Minimum width that the AppWidget can be resized to. -->
+ <attr name="minResizeWidth" format="dimension"/>
+ <!-- Minimum height that the AppWidget can be resized to. -->
+ <attr name="minResizeHeight" format="dimension"/>
<!-- Update period in milliseconds, or 0 if the AppWidget will update itself. -->
<attr name="updatePeriodMillis" format="integer" />
<!-- A resource id of a layout. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 2ba4e66..0ed8076 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -67,9 +67,9 @@
<dimen name="multiwaveview_hit_radius">60dip</dimen>
<!-- Preference activity side margins -->
- <dimen name="preference_screen_side_margin">0dp</dimen>
+ <dimen name="preference_screen_side_margin">16dp</dimen>
<!-- Preference activity side margins negative-->
- <dimen name="preference_screen_side_margin_negative">0dp</dimen>
+ <dimen name="preference_screen_side_margin_negative">16dp</dimen>
<!-- Preference activity top margin -->
<dimen name="preference_screen_top_margin">0dp</dimen>
<!-- Preference activity bottom margin -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index f464623..ba2a036 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1831,4 +1831,6 @@
<public type="color" name="holo_purple" />
<public type="color" name="holo_blue_bright" />
+ <public type="attr" name="minResizeWidth" />
+ <public type="attr" name="minResizeHeight" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d0e3f14..64f7316 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2152,6 +2152,22 @@
not implement this feature.</string>
<!-- Title of an application permission, listed so the user can choose whether
+ they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permlab_readWriteOwnVoicemail">Access voicemails managed by this application</string>
+ <!-- Description of an application permission, listed so the user can choose whether
+ they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_readWriteOwnVoicemail">Allows the application to store and retrieve only
+ voicemails that its associated service can access.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether
+ they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permlab_readWriteAllVoicemail">Access all voicemails</string>
+ <!-- Description of an application permission, listed so the user can choose whether
+ they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+ <string name="permdesc_readWriteAllVoicemail">Allows the application to store and retrieve all
+ voicemails that this device can access.</string>
+
+ <!-- Title of an application permission, listed so the user can choose whether
they want to allow the application to do this. -->
<string name="permlab_writeGeolocationPermissions">Modify Browser geolocation permissions</string>
<!-- Description of an application permission, listed so the user can choose whether
diff --git a/core/tests/coretests/src/android/util/JsonReaderTest.java b/core/tests/coretests/src/android/util/JsonReaderTest.java
index 440aeb5..0b50af3 100644
--- a/core/tests/coretests/src/android/util/JsonReaderTest.java
+++ b/core/tests/coretests/src/android/util/JsonReaderTest.java
@@ -858,7 +858,7 @@ public final class JsonReaderTest extends TestCase {
}
public void testFailWithPosition() throws IOException {
- testFailWithPosition("Expected literal value at line 6 column 3",
+ testFailWithPosition("Expected literal value at line 6 column 3",
"[\n\n\n\n\n0,}]");
}
diff --git a/data/fonts/DroidKufi-Bold.ttf b/data/fonts/DroidKufi-Bold.ttf
new file mode 100644
index 0000000..650919e
--- /dev/null
+++ b/data/fonts/DroidKufi-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidKufi-Regular.ttf b/data/fonts/DroidKufi-Regular.ttf
new file mode 100644
index 0000000..af85975
--- /dev/null
+++ b/data/fonts/DroidKufi-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Bold.ttf b/data/fonts/DroidNaskh-Bold.ttf
new file mode 100644
index 0000000..6b7d4f0
--- /dev/null
+++ b/data/fonts/DroidNaskh-Bold.ttf
Binary files differ
diff --git a/data/fonts/DroidNaskh-Regular.ttf b/data/fonts/DroidNaskh-Regular.ttf
new file mode 100644
index 0000000..d11e1ae
--- /dev/null
+++ b/data/fonts/DroidNaskh-Regular.ttf
Binary files differ
diff --git a/data/fonts/DroidSansArabic.ttf b/data/fonts/DroidSansArabic.ttf
deleted file mode 100644
index bdefaac..0000000
--- a/data/fonts/DroidSansArabic.ttf
+++ /dev/null
Binary files differ
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index c0d9153..6ac615d 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -25,7 +25,12 @@
<familyset>
<family>
<fileset>
- <file>DroidSansArabic.ttf</file>
+ <file>DroidNaskh-Regular.ttf</file>
+ </fileset>
+ </family>
+ <family>
+ <fileset>
+ <file>DroidSansEthiopic-Regular.ttf</file>
</fileset>
</family>
<family>
diff --git a/data/fonts/fonts.mk b/data/fonts/fonts.mk
index 57a1bab..9a590bb 100644
--- a/data/fonts/fonts.mk
+++ b/data/fonts/fonts.mk
@@ -17,7 +17,8 @@
PRODUCT_COPY_FILES := \
frameworks/base/data/fonts/DroidSans.ttf:system/fonts/DroidSans.ttf \
frameworks/base/data/fonts/DroidSans-Bold.ttf:system/fonts/DroidSans-Bold.ttf \
- frameworks/base/data/fonts/DroidSansArabic.ttf:system/fonts/DroidSansArabic.ttf \
+ frameworks/base/data/fonts/DroidNaskh-Regular.ttf:system/fonts/DroidNaskh-Regular.ttf \
+ frameworks/base/data/fonts/DroidSansEthiopic-Regular.ttf:system/fonts/DroidSansEthiopic-Regular.ttf \
frameworks/base/data/fonts/DroidSansHebrew-Regular.ttf:system/fonts/DroidSansHebrew-Regular.ttf \
frameworks/base/data/fonts/DroidSansHebrew-Bold.ttf:system/fonts/DroidSansHebrew-Bold.ttf \
frameworks/base/data/fonts/DroidSansThai.ttf:system/fonts/DroidSansThai.ttf \
diff --git a/docs/html/guide/practices/design/jni.jd b/docs/html/guide/practices/design/jni.jd
index 3e9ddc4..39624f5 100644
--- a/docs/html/guide/practices/design/jni.jd
+++ b/docs/html/guide/practices/design/jni.jd
@@ -175,8 +175,8 @@ The global reference is guaranteed to be valid until you call
<p>This pattern is commonly used when caching copies of class objects obtained
from <code>FindClass</code>, e.g.:</p>
-<pre>jclass* localClass = env-&gt;FindClass("MyClass");
-jclass* globalClass = (jclass*) env-&gt;NewGlobalRef(localClass);</pre>
+<pre>jclass localClass = env-&gt;FindClass("MyClass");
+jclass globalClass = reinterpret_cast&lt;jclass&gt;(env-&gt;NewGlobalRef(localClass));</pre>
<p>All JNI methods accept both local and global references as arguments.
It's possible for references to the same object to have different values;
@@ -215,10 +215,9 @@ to detach the thread soon.</p>
<a name="UTF_8_and_UTF_16_strings" id="UTF_8_and_UTF_16_strings"></a>
<h2>UTF-8 and UTF-16 Strings</h2>
-<p>The Java programming language uses UTF-16. For convenience, JNI provides methods that work with "modified UTF-8" encoding
-as well. (Some VMs use the modified UTF-8 internally to store strings; ours do not.) The
-modified encoding only supports the 8- and 16-bit forms, and stores ASCII NUL values in a 16-bit encoding.
-The nice thing about it is that you can count on having C-style zero-terminated strings,
+<p>The Java programming language uses UTF-16. For convenience, JNI provides methods that work with <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> as well. The
+modified encoding is useful for C code because it encodes \u0000 as 0xc0 0x80 instead of 0x00.
+The nice thing about this is that you can count on having C-style zero-terminated strings,
suitable for use with standard libc string functions. The down side is that you cannot pass
arbitrary UTF-8 data into the VM and expect it to work correctly.</p>
@@ -235,11 +234,11 @@ are C-style pointers to primitive data rather than local references. They
are guaranteed valid until Release is called, which means they are not
released when the native method returns.</p>
-<p><strong>Data passed to NewStringUTF must be in "modified" UTF-8 format</strong>. A
+<p><strong>Data passed to NewStringUTF must be in Modified UTF-8 format</strong>. A
common mistake is reading character data from a file or network stream
and handing it to <code>NewStringUTF</code> without filtering it.
Unless you know the data is 7-bit ASCII, you need to strip out high-ASCII
-characters or convert them to proper "modified" UTF-8 form. If you don't,
+characters or convert them to proper Modified UTF-8 form. If you don't,
the UTF-16 conversion will likely not be what you expect. The extended
JNI checks will scan strings and warn you about invalid data, but they
won't catch everything.</p>
@@ -321,10 +320,10 @@ and <code>GetStringChars</code> that may be very helpful when all you want
to do is copy data in or out. Consider the following:</p>
<pre>
- jbyte* data = env->GetByteArrayElements(array, NULL);
+ jbyte* data = env-&gt;GetByteArrayElements(array, NULL);
if (data != NULL) {
memcpy(buffer, data, len);
- env->ReleaseByteArrayElements(array, data, JNI_ABORT);
+ env-&gt;ReleaseByteArrayElements(array, data, JNI_ABORT);
}</pre>
<p>This grabs the array, copies the first <code>len</code> byte
@@ -335,7 +334,7 @@ we use <code>JNI_ABORT</code> so there's no chance of a third copy.</p>
<p>We can accomplish the same thing with this:</p>
<pre>
- env->GetByteArrayRegion(array, 0, len, buffer);</pre>
+ env-&gt;GetByteArrayRegion(array, 0, len, buffer);</pre>
<p>This has several advantages:</p>
<ul>
@@ -433,7 +432,7 @@ method call.</li>
<li> Check for calls to inappropriate functions between Critical get/release calls.</li>
<li> Check that JNIEnv structs aren't being shared between threads.</li>
<li> Make sure local references aren't used outside their allowed lifespan.</li>
-<li> UTF-8 strings contain only valid "modified UTF-8" data.</li>
+<li> UTF-8 strings contain only valid <a href="http://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8">Modified UTF-8</a> data.</li>
</ul>
<p>Accessibility of methods and fields (i.e. public vs. private) is not
@@ -476,20 +475,21 @@ library name, e.g. to load "libfubar.so" you would pass in "fubar".</li>
<li> Provide a native function: <code><strong>jint JNI_OnLoad(JavaVM* vm, void* reserved)</strong></code></li>
<li>In <code>JNI_OnLoad</code>, register all of your native methods. You
should declare
-the methods "static" so the names don't take up space in the symbol table
+the functions <code>static</code> so the names don't take up space in the symbol table
on the device.</li>
</ul>
<p>The <code>JNI_OnLoad</code> function should look something like this if
-written in C:</p>
+written in C++:</p>
<pre>jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env;
- if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_6) != JNI_OK)
+ if (vm-&gt;GetEnv(reinterpret_cast&lt;void**&gt;(&env), JNI_VERSION_1_6) != JNI_OK) {
return -1;
+ }
- /* get class with (*env)->FindClass */
- /* register methods with (*env)->RegisterNatives */
+ // Get jclass with env-&gt;FindClass.
+ // Register methods with env-&gt;RegisterNatives.
return JNI_VERSION_1_6;
}</pre>
@@ -603,7 +603,7 @@ Some common reasons for this are:</p>
is commonly caused by:
<ul>
<li>For lazy method lookup, failing to declare C++ functions
- with <code>extern C</code>. You can use <code>arm-eabi-nm</code>
+ with <code>extern "C"</code>. You can use <code>arm-eabi-nm</code>
to see the symbols as they appear in the library; if they look
mangled (e.g. <code>_Z15Java_Foo_myfuncP7_JNIEnvP7_jclass</code>
rather than <code>Java_Foo_myfunc</code>) then you need to
diff --git a/include/gui/ISurfaceTexture.h b/include/gui/ISurfaceTexture.h
index 5b5b731..e764425 100644
--- a/include/gui/ISurfaceTexture.h
+++ b/include/gui/ISurfaceTexture.h
@@ -78,7 +78,12 @@ protected:
// client for this buffer. The timestamp is measured in nanoseconds, and
// must be monotonically increasing. Its other properties (zero point, etc)
// are client-dependent, and should be documented by the client.
- virtual status_t queueBuffer(int slot, int64_t timestamp) = 0;
+ //
+ // outWidth, outHeight and outTransform are filed with the default width
+ // default height of the window and current transform applied to buffers,
+ // respectively.
+ virtual status_t queueBuffer(int slot, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) = 0;
// cancelBuffer indicates that the client does not wish to fill in the
// buffer associated with slot and transfers ownership of the slot back to
@@ -87,6 +92,7 @@ protected:
virtual status_t setCrop(const Rect& reg) = 0;
virtual status_t setTransform(uint32_t transform) = 0;
+ virtual status_t setScalingMode(int mode) = 0;
// getAllocator retrieves the binder object that must be referenced as long
// as the GraphicBuffers dequeued from this ISurfaceTexture are referenced.
diff --git a/include/gui/SurfaceTexture.h b/include/gui/SurfaceTexture.h
index 4080f27..945f4bc 100644
--- a/include/gui/SurfaceTexture.h
+++ b/include/gui/SurfaceTexture.h
@@ -84,10 +84,12 @@ public:
// nanoseconds, and must be monotonically increasing. Its other semantics
// (zero point, etc) are client-dependent and should be documented by the
// client.
- virtual status_t queueBuffer(int buf, int64_t timestamp);
+ virtual status_t queueBuffer(int buf, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
virtual void cancelBuffer(int buf);
virtual status_t setCrop(const Rect& reg);
virtual status_t setTransform(uint32_t transform);
+ virtual status_t setScalingMode(int mode);
virtual int query(int what, int* value);
@@ -185,6 +187,9 @@ public:
// getCurrentTransform returns the transform of the current buffer
uint32_t getCurrentTransform() const;
+ // getCurrentScalingMode returns the scaling mode of the current buffer
+ uint32_t getCurrentScalingMode() const;
+
// dump our state in a String
void dump(String8& result) const;
void dump(String8& result, const char* prefix, char* buffer, size_t SIZE) const;
@@ -220,6 +225,7 @@ private:
mBufferState(BufferSlot::FREE),
mRequestBufferCalled(false),
mTransform(0),
+ mScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mTimestamp(0) {
mCrop.makeInvalid();
}
@@ -281,6 +287,11 @@ private:
// slot.
uint32_t mTransform;
+ // mScalingMode is the current scaling mode for this buffer slot. This
+ // gets set to mNextScalingMode each time queueBuffer gets called for
+ // this slot.
+ uint32_t mScalingMode;
+
// mTimestamp is the current timestamp for this buffer slot. This gets
// to set by queueBuffer each time this slot is queued.
int64_t mTimestamp;
@@ -337,20 +348,24 @@ private:
sp<GraphicBuffer> mCurrentTextureBuf;
// mCurrentCrop is the crop rectangle that applies to the current texture.
- // It gets set to mLastQueuedCrop each time updateTexImage is called.
+ // It gets set each time updateTexImage is called.
Rect mCurrentCrop;
// mCurrentTransform is the transform identifier for the current texture. It
- // gets set to mLastQueuedTransform each time updateTexImage is called.
+ // gets set each time updateTexImage is called.
uint32_t mCurrentTransform;
+ // mCurrentScalingMode is the scaling mode for the current texture. It gets
+ // set to each time updateTexImage is called.
+ uint32_t mCurrentScalingMode;
+
// mCurrentTransformMatrix is the transform matrix for the current texture.
// It gets computed by computeTransformMatrix each time updateTexImage is
// called.
float mCurrentTransformMatrix[16];
// mCurrentTimestamp is the timestamp for the current texture. It
- // gets set to mLastQueuedTimestamp each time updateTexImage is called.
+ // gets set each time updateTexImage is called.
int64_t mCurrentTimestamp;
// mNextCrop is the crop rectangle that will be used for the next buffer
@@ -361,6 +376,10 @@ private:
// buffer that gets queued. It is set by calling setTransform.
uint32_t mNextTransform;
+ // mNextScalingMode is the scaling mode that will be used for the next
+ // buffers that get queued. It is set by calling setScalingMode.
+ int mNextScalingMode;
+
// mTexName is the name of the OpenGL texture to which streamed images will
// be bound when updateTexImage is called. It is set at construction time
// changed with a call to setTexName.
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index cfe2aa1..829d8ab 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -63,6 +63,7 @@ private:
int dispatchSetBuffersGeometry(va_list args);
int dispatchSetBuffersDimensions(va_list args);
int dispatchSetBuffersFormat(va_list args);
+ int dispatchSetScalingMode(va_list args);
int dispatchSetBuffersTransform(va_list args);
int dispatchSetBuffersTimestamp(va_list args);
int dispatchSetCrop(va_list args);
@@ -84,6 +85,7 @@ protected:
virtual int setBufferCount(int bufferCount);
virtual int setBuffersDimensions(int w, int h);
virtual int setBuffersFormat(int format);
+ virtual int setScalingMode(int mode);
virtual int setBuffersTransform(int transform);
virtual int setBuffersTimestamp(int64_t timestamp);
virtual int setCrop(Rect const* rect);
@@ -149,6 +151,18 @@ private:
// dequeued format or to mReqFormat if no buffer was dequeued.
uint32_t mQueryFormat;
+ // mDefaultWidth is default width of the window, regardless of the
+ // set_dimension call
+ uint32_t mDefaultWidth;
+
+ // mDefaultHeight is default width of the window, regardless of the
+ // set_dimension call
+ uint32_t mDefaultHeight;
+
+ // mTransformHint is the transform probably applied to buffers of this
+ // window. this is only a hint, actual transform may differ.
+ uint32_t mTransformHint;
+
// mMutex is the mutex used to prevent concurrent access to the member
// variables of SurfaceTexture objects. It must be locked whenever the
// member variables are accessed.
diff --git a/libs/gui/ISurfaceTexture.cpp b/libs/gui/ISurfaceTexture.cpp
index 41434a4..be90e2e 100644
--- a/libs/gui/ISurfaceTexture.cpp
+++ b/libs/gui/ISurfaceTexture.cpp
@@ -43,6 +43,7 @@ enum {
SET_SYNCHRONOUS_MODE,
CONNECT,
DISCONNECT,
+ SET_SCALING_MODE,
};
@@ -92,12 +93,16 @@ public:
return result;
}
- virtual status_t queueBuffer(int buf, int64_t timestamp) {
+ virtual status_t queueBuffer(int buf, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
data.writeInt32(buf);
data.writeInt64(timestamp);
remote()->transact(QUEUE_BUFFER, data, &reply);
+ *outWidth = reply.readInt32();
+ *outHeight = reply.readInt32();
+ *outTransform = reply.readInt32();
status_t result = reply.readInt32();
return result;
}
@@ -130,6 +135,15 @@ public:
return result;
}
+ virtual status_t setScalingMode(int mode) {
+ Parcel data, reply;
+ data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
+ data.writeInt32(mode);
+ remote()->transact(SET_SCALING_MODE, data, &reply);
+ status_t result = reply.readInt32();
+ return result;
+ }
+
virtual sp<IBinder> getAllocator() {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceTexture::getInterfaceDescriptor());
@@ -216,7 +230,12 @@ status_t BnSurfaceTexture::onTransact(
CHECK_INTERFACE(ISurfaceTexture, data, reply);
int buf = data.readInt32();
int64_t timestamp = data.readInt64();
- status_t result = queueBuffer(buf, timestamp);
+ uint32_t outWidth, outHeight, outTransform;
+ status_t result = queueBuffer(buf, timestamp,
+ &outWidth, &outHeight, &outTransform);
+ reply->writeInt32(outWidth);
+ reply->writeInt32(outHeight);
+ reply->writeInt32(outTransform);
reply->writeInt32(result);
return NO_ERROR;
} break;
@@ -244,6 +263,13 @@ status_t BnSurfaceTexture::onTransact(
reply->writeInt32(result);
return NO_ERROR;
} break;
+ case SET_SCALING_MODE: {
+ CHECK_INTERFACE(ISurfaceTexture, data, reply);
+ int mode = data.readInt32();
+ status_t result = setScalingMode(mode);
+ reply->writeInt32(result);
+ return NO_ERROR;
+ } break;
case GET_ALLOCATOR: {
CHECK_INTERFACE(ISurfaceTexture, data, reply);
sp<IBinder> result = getAllocator();
diff --git a/libs/gui/SurfaceTexture.cpp b/libs/gui/SurfaceTexture.cpp
index a12d40a..0f08570 100644
--- a/libs/gui/SurfaceTexture.cpp
+++ b/libs/gui/SurfaceTexture.cpp
@@ -90,6 +90,7 @@ SurfaceTexture::SurfaceTexture(GLuint tex, bool allowSynchronousMode) :
mCurrentTransform(0),
mCurrentTimestamp(0),
mNextTransform(0),
+ mNextScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mTexName(tex),
mSynchronousMode(false),
mAllowSynchronousMode(allowSynchronousMode),
@@ -401,7 +402,8 @@ status_t SurfaceTexture::setSynchronousMode(bool enabled) {
return err;
}
-status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
+status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
LOGV("SurfaceTexture::queueBuffer");
sp<FrameAvailableListener> listener;
@@ -453,6 +455,7 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
mSlots[buf].mBufferState = BufferSlot::QUEUED;
mSlots[buf].mCrop = mNextCrop;
mSlots[buf].mTransform = mNextTransform;
+ mSlots[buf].mScalingMode = mNextScalingMode;
mSlots[buf].mTimestamp = timestamp;
mDequeueCondition.signal();
} // scope for the lock
@@ -461,6 +464,11 @@ status_t SurfaceTexture::queueBuffer(int buf, int64_t timestamp) {
if (listener != 0) {
listener->onFrameAvailable();
}
+
+ *outWidth = mDefaultWidth;
+ *outHeight = mDefaultHeight;
+ *outTransform = 0;
+
return OK;
}
@@ -542,6 +550,22 @@ status_t SurfaceTexture::disconnect(int api) {
return err;
}
+status_t SurfaceTexture::setScalingMode(int mode) {
+ LOGV("SurfaceTexture::setScalingMode(%d)", mode);
+
+ switch (mode) {
+ case NATIVE_WINDOW_SCALING_MODE_FREEZE:
+ case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
+ break;
+ default:
+ return BAD_VALUE;
+ }
+
+ Mutex::Autolock lock(mMutex);
+ mNextScalingMode = mode;
+ return OK;
+}
+
status_t SurfaceTexture::updateTexImage() {
LOGV("SurfaceTexture::updateTexImage");
Mutex::Autolock lock(mMutex);
@@ -602,6 +626,7 @@ status_t SurfaceTexture::updateTexImage() {
mCurrentTextureBuf = mSlots[buf].mGraphicBuffer;
mCurrentCrop = mSlots[buf].mCrop;
mCurrentTransform = mSlots[buf].mTransform;
+ mCurrentScalingMode = mSlots[buf].mScalingMode;
mCurrentTimestamp = mSlots[buf].mTimestamp;
computeCurrentTransformMatrix();
@@ -809,6 +834,11 @@ uint32_t SurfaceTexture::getCurrentTransform() const {
return mCurrentTransform;
}
+uint32_t SurfaceTexture::getCurrentScalingMode() const {
+ Mutex::Autolock lock(mMutex);
+ return mCurrentScalingMode;
+}
+
int SurfaceTexture::query(int what, int* outValue)
{
Mutex::Autolock lock(mMutex);
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index d5b7c89..1dc6cd2 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -222,26 +222,38 @@ int SurfaceTextureClient::queueBuffer(android_native_buffer_t* buffer) {
if (i < 0) {
return i;
}
- mSurfaceTexture->queueBuffer(i, timestamp);
+ mSurfaceTexture->queueBuffer(i, timestamp,
+ &mDefaultWidth, &mDefaultHeight, &mTransformHint);
return OK;
}
int SurfaceTextureClient::query(int what, int* value) const {
LOGV("SurfaceTextureClient::query");
- switch (what) {
- case NATIVE_WINDOW_FORMAT:
- if (mReqFormat) {
- *value = mReqFormat;
- return NO_ERROR;
+ { // scope for the lock
+ Mutex::Autolock lock(mMutex);
+ switch (what) {
+ case NATIVE_WINDOW_FORMAT:
+ if (mReqFormat) {
+ *value = mReqFormat;
+ return NO_ERROR;
+ }
+ break;
+ case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
+ *value = 0;
+ return NO_ERROR;
+ case NATIVE_WINDOW_CONCRETE_TYPE:
+ *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
+ return NO_ERROR;
+ case NATIVE_WINDOW_DEFAULT_WIDTH:
+ *value = mDefaultWidth;
+ return NO_ERROR;
+ case NATIVE_WINDOW_DEFAULT_HEIGHT:
+ *value = mDefaultHeight;
+ return NO_ERROR;
+ case NATIVE_WINDOW_TRANSFORM_HINT:
+ *value = mTransformHint;
+ return NO_ERROR;
}
- break;
- case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
- // TODO: this is not needed anymore
- *value = 0;
- return NO_ERROR;
- case NATIVE_WINDOW_CONCRETE_TYPE:
- *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
- return NO_ERROR;
}
return mSurfaceTexture->query(what, value);
}
@@ -286,6 +298,9 @@ int SurfaceTextureClient::perform(int operation, va_list args)
case NATIVE_WINDOW_UNLOCK_AND_POST:
res = dispatchUnlockAndPost(args);
break;
+ case NATIVE_WINDOW_SET_SCALING_MODE:
+ res = dispatchSetScalingMode(args);
+ break;
default:
res = NAME_NOT_FOUND;
break;
@@ -340,6 +355,11 @@ int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) {
return setBuffersFormat(f);
}
+int SurfaceTextureClient::dispatchSetScalingMode(va_list args) {
+ int m = va_arg(args, int);
+ return setScalingMode(m);
+}
+
int SurfaceTextureClient::dispatchSetBuffersTransform(va_list args) {
int transform = va_arg(args, int);
return setBuffersTransform(transform);
@@ -456,6 +476,18 @@ int SurfaceTextureClient::setBuffersFormat(int format)
return NO_ERROR;
}
+int SurfaceTextureClient::setScalingMode(int mode)
+{
+ LOGV("SurfaceTextureClient::setScalingMode(%d)", mode);
+ Mutex::Autolock lock(mMutex);
+ // mode is validated on the server
+ status_t err = mSurfaceTexture->setScalingMode(mode);
+ LOGE_IF(err, "ISurfaceTexture::setScalingMode(%d) returned %s",
+ mode, strerror(-err));
+
+ return err;
+}
+
int SurfaceTextureClient::setBuffersTransform(int transform)
{
LOGV("SurfaceTextureClient::setBuffersTransform");
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index a349121..85a9762 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -125,6 +125,7 @@ OpenGLRenderer::~OpenGLRenderer() {
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::setViewport(int width, int height) {
+ glDisable(GL_DITHER);
glViewport(0, 0, width, height);
mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
@@ -151,7 +152,6 @@ void OpenGLRenderer::prepareDirty(float left, float top, float right, float bott
mSaveCount = 1;
glViewport(0, 0, mWidth, mHeight);
- glDisable(GL_DITHER);
glEnable(GL_SCISSOR_TEST);
glScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index a8aa0c7..58d3e5c 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -128,7 +128,7 @@ LOCAL_SRC_FILES:= \
driver/rsdShaderCache.cpp \
driver/rsdVertexArray.cpp
-LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc
+LOCAL_SHARED_LIBRARIES += libz libcutils libutils libEGL libGLESv1_CM libGLESv2 libui libbcc libbcinfo
LOCAL_STATIC_LIBRARIES := libdex libft2
diff --git a/libs/rs/driver/rsdBcc.cpp b/libs/rs/driver/rsdBcc.cpp
index bbf2836..0c0aa10 100644
--- a/libs/rs/driver/rsdBcc.cpp
+++ b/libs/rs/driver/rsdBcc.cpp
@@ -19,6 +19,8 @@
#include "rsdBcc.h"
#include "rsdRuntime.h"
+#include <bcinfo/bcinfo.h>
+
#include "rsContext.h"
#include "rsScriptC.h"
@@ -38,22 +40,14 @@ struct DrvScript {
BCCScriptRef mBccScript;
- uint32_t mInvokeFunctionCount;
+ struct BCScriptMetadata *mScriptMetadata;
+
InvokeFunc_t *mInvokeFunctions;
- uint32_t mFieldCount;
void ** mFieldAddress;
bool * mFieldIsObject;
const uint8_t * mScriptText;
uint32_t mScriptTextLength;
-
- //uint32_t * mObjectSlots;
- //uint32_t mObjectSlotCount;
-
- uint32_t mPragmaCount;
- const char ** mPragmaKeys;
- const char ** mPragmaValues;
-
};
@@ -77,7 +71,7 @@ bool rsdScriptInit(const Context *rsc,
pthread_mutex_lock(&rsdgInitMutex);
char *cachePath = NULL;
- uint32_t objectSlotCount = 0;
+ struct BCScriptMetadata *md = NULL;
DrvScript *drv = (DrvScript *)calloc(1, sizeof(DrvScript));
if (drv == NULL) {
@@ -90,6 +84,14 @@ bool rsdScriptInit(const Context *rsc,
drv->mScriptText = bitcode;
drv->mScriptTextLength = bitcodeSize;
+ md = bcinfoGetScriptMetadata((const char*)drv->mScriptText,
+ drv->mScriptTextLength, 0);
+ if (!md) {
+ LOGE("bcinfo: failed to read script metadata");
+ goto error;
+ }
+ drv->mScriptMetadata = md;
+
//LOGE("mBccScript %p", script->mBccScript);
if (bccRegisterSymbolCallback(drv->mBccScript, &rsdLookupRuntimeStub, script) != 0) {
@@ -120,59 +122,42 @@ bool rsdScriptInit(const Context *rsc,
drv->mRoot = reinterpret_cast<int (*)()>(bccGetFuncAddr(drv->mBccScript, "root"));
drv->mInit = reinterpret_cast<void (*)()>(bccGetFuncAddr(drv->mBccScript, "init"));
- drv->mInvokeFunctionCount = bccGetExportFuncCount(drv->mBccScript);
- if (drv->mInvokeFunctionCount <= 0)
+ if (md->exportFuncCount > 0) {
+ drv->mInvokeFunctions = (InvokeFunc_t*) calloc(md->exportFuncCount,
+ sizeof(InvokeFunc_t));
+ bccGetExportFuncList(drv->mBccScript,
+ md->exportFuncCount,
+ (void **) drv->mInvokeFunctions);
+ } else {
drv->mInvokeFunctions = NULL;
- else {
- drv->mInvokeFunctions = (InvokeFunc_t*) calloc(drv->mInvokeFunctionCount, sizeof(InvokeFunc_t));
- bccGetExportFuncList(drv->mBccScript, drv->mInvokeFunctionCount, (void **) drv->mInvokeFunctions);
}
- drv->mFieldCount = bccGetExportVarCount(drv->mBccScript);
- if (drv->mFieldCount <= 0) {
+ if (md->exportVarCount > 0) {
+ drv->mFieldAddress = (void **) calloc(md->exportVarCount,
+ sizeof(void*));
+ drv->mFieldIsObject = (bool *) calloc(md->exportVarCount, sizeof(bool));
+ bccGetExportVarList(drv->mBccScript,
+ md->exportVarCount,
+ (void **) drv->mFieldAddress);
+ } else {
drv->mFieldAddress = NULL;
drv->mFieldIsObject = NULL;
- } else {
- drv->mFieldAddress = (void **) calloc(drv->mFieldCount, sizeof(void *));
- drv->mFieldIsObject = (bool *) calloc(drv->mFieldCount, sizeof(bool));
- bccGetExportVarList(drv->mBccScript, drv->mFieldCount, (void **) drv->mFieldAddress);
}
- objectSlotCount = bccGetObjectSlotCount(drv->mBccScript);
- if (objectSlotCount) {
- uint32_t * slots = new uint32_t[objectSlotCount];
- bccGetObjectSlotList(drv->mBccScript, objectSlotCount, slots);
- for (uint32_t ct=0; ct < objectSlotCount; ct++) {
- drv->mFieldIsObject[slots[ct]] = true;
+ if (md->objectSlotCount) {
+ for (uint32_t ct=0; ct < md->objectSlotCount; ct++) {
+ drv->mFieldIsObject[md->objectSlotList[ct]] = true;
}
- delete [] slots;
}
- uint32_t mPragmaCount;
- const char ** mPragmaKeys;
- const char ** mPragmaValues;
-
- drv->mPragmaCount = bccGetPragmaCount(drv->mBccScript);
- if (drv->mPragmaCount <= 0) {
- drv->mPragmaKeys = NULL;
- drv->mPragmaValues = NULL;
- } else {
- drv->mPragmaKeys = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
- drv->mPragmaValues = (const char **) calloc(drv->mPragmaCount, sizeof(const char *));
- bccGetPragmaList(drv->mBccScript, drv->mPragmaCount, drv->mPragmaKeys, drv->mPragmaValues);
- }
-
-
-
// Copy info over to runtime
- script->mHal.info.exportedFunctionCount = drv->mInvokeFunctionCount;
- script->mHal.info.exportedVariableCount = drv->mFieldCount;
- script->mHal.info.exportedPragmaCount = drv->mPragmaCount;
- script->mHal.info.exportedPragmaKeyList = drv->mPragmaKeys;
- script->mHal.info.exportedPragmaValueList = drv->mPragmaValues;
+ script->mHal.info.exportedFunctionCount = md->exportFuncCount;
+ script->mHal.info.exportedVariableCount = md->exportVarCount;
+ script->mHal.info.exportedPragmaCount = md->pragmaCount;
+ script->mHal.info.exportedPragmaKeyList = md->pragmaKeyList;
+ script->mHal.info.exportedPragmaValueList = md->pragmaValueList;
script->mHal.info.root = drv->mRoot;
-
pthread_mutex_unlock(&rsdgInitMutex);
return true;
@@ -460,9 +445,10 @@ void rsdScriptSetGlobalObj(const Context *dc, const Script *script, uint32_t slo
void rsdScriptDestroy(const Context *dc, Script *script) {
DrvScript *drv = (DrvScript *)script->mHal.drv;
+ struct BCScriptMetadata *md = drv->mScriptMetadata;
if (drv->mFieldAddress) {
- for (size_t ct=0; ct < drv->mFieldCount; ct++) {
+ for (size_t ct = 0; ct < md->exportVarCount; ct++) {
if (drv->mFieldIsObject[ct]) {
// The field address can be NULL if the script-side has
// optimized the corresponding global variable away.
@@ -471,18 +457,18 @@ void rsdScriptDestroy(const Context *dc, Script *script) {
}
}
}
- delete [] drv->mFieldAddress;
- delete [] drv->mFieldIsObject;
+ free(drv->mFieldAddress);
drv->mFieldAddress = NULL;
- drv->mFieldIsObject = NULL;
- drv->mFieldCount = 0;
- }
+ free(drv->mFieldIsObject);
+ drv->mFieldIsObject = NULL; }
if (drv->mInvokeFunctions) {
- delete [] drv->mInvokeFunctions;
+ free(drv->mInvokeFunctions);
drv->mInvokeFunctions = NULL;
- drv->mInvokeFunctionCount = 0;
}
+
+ bcinfoReleaseScriptMetadata(&drv->mScriptMetadata);
+
free(drv);
script->mHal.drv = NULL;
diff --git a/libs/rs/rsContext.cpp b/libs/rs/rsContext.cpp
index 447a7ff..decd9f1 100644
--- a/libs/rs/rsContext.cpp
+++ b/libs/rs/rsContext.cpp
@@ -442,6 +442,7 @@ void Context::setSurface(uint32_t w, uint32_t h, RsNativeWindow sur) {
if (mWidth && mHeight) {
mStateVertex.updateSize(this);
+ mFBOCache.updateSize();
}
}
diff --git a/libs/rs/rsFBOCache.h b/libs/rs/rsFBOCache.h
index f42e1f3..5d58ba4 100644
--- a/libs/rs/rsFBOCache.h
+++ b/libs/rs/rsFBOCache.h
@@ -38,6 +38,7 @@ public:
void resetAll(Context *);
void setup(Context *);
+ void updateSize() { mDirty = true; }
struct Hal {
mutable void *drv;
diff --git a/libs/ui/FramebufferNativeWindow.cpp b/libs/ui/FramebufferNativeWindow.cpp
index 794747d..412552e 100644
--- a/libs/ui/FramebufferNativeWindow.cpp
+++ b/libs/ui/FramebufferNativeWindow.cpp
@@ -289,6 +289,18 @@ int FramebufferNativeWindow::query(const ANativeWindow* window,
case NATIVE_WINDOW_CONCRETE_TYPE:
*value = NATIVE_WINDOW_FRAMEBUFFER;
return NO_ERROR;
+ case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER:
+ *value = 0;
+ return NO_ERROR;
+ case NATIVE_WINDOW_DEFAULT_WIDTH:
+ *value = fb->width;
+ return NO_ERROR;
+ case NATIVE_WINDOW_DEFAULT_HEIGHT:
+ *value = fb->height;
+ return NO_ERROR;
+ case NATIVE_WINDOW_TRANSFORM_HINT:
+ *value = 0;
+ return NO_ERROR;
}
*value = 0;
return BAD_VALUE;
@@ -299,18 +311,38 @@ int FramebufferNativeWindow::perform(ANativeWindow* window,
{
switch (operation) {
case NATIVE_WINDOW_SET_USAGE:
- case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+ // TODO: we should implement this
+ return NO_ERROR;
case NATIVE_WINDOW_CONNECT:
+ // TODO: we should implement this
+ return NO_ERROR;
case NATIVE_WINDOW_DISCONNECT:
- break;
+ // TODO: we should implement this
+ return NO_ERROR;
case NATIVE_WINDOW_LOCK:
return INVALID_OPERATION;
case NATIVE_WINDOW_UNLOCK_AND_POST:
return INVALID_OPERATION;
- default:
- return NAME_NOT_FOUND;
+ case NATIVE_WINDOW_SET_CROP:
+ return INVALID_OPERATION;
+ case NATIVE_WINDOW_SET_BUFFER_COUNT:
+ // TODO: we should implement this
+ return INVALID_OPERATION;
+ case NATIVE_WINDOW_SET_BUFFERS_GEOMETRY:
+ return INVALID_OPERATION;
+ case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM:
+ return INVALID_OPERATION;
+ case NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP:
+ return INVALID_OPERATION;
+ case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
+ return INVALID_OPERATION;
+ case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
+ // TODO: we should implement this
+ return NO_ERROR;
+ case NATIVE_WINDOW_SET_SCALING_MODE:
+ return INVALID_OPERATION;
}
- return NO_ERROR;
+ return NAME_NOT_FOUND;
}
// ----------------------------------------------------------------------------
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 253010c..7258e11 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -297,6 +297,9 @@ public class AudioManager {
*/
public static final int RINGER_MODE_NORMAL = 2;
+ // maximum valid ringer mode value. Values must start from 0 and be contiguous.
+ private static final int RINGER_MODE_MAX = RINGER_MODE_NORMAL;
+
/**
* Vibrate type that corresponds to the ringer.
*
@@ -540,6 +543,21 @@ public class AudioManager {
}
/**
+ * Checks valid ringer mode values.
+ *
+ * @return true if the ringer mode indicated is valid, false otherwise.
+ *
+ * @see #setRingerMode(int)
+ * @hide
+ */
+ public static boolean isValidRingerMode(int ringerMode) {
+ if (ringerMode < 0 || ringerMode > RINGER_MODE_MAX) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
* Returns the maximum volume index for a particular stream.
*
* @param streamType The stream type whose maximum volume index is returned.
@@ -601,6 +619,9 @@ public class AudioManager {
* @see #getRingerMode()
*/
public void setRingerMode(int ringerMode) {
+ if (!isValidRingerMode(ringerMode)) {
+ return;
+ }
IAudioService service = getService();
try {
service.setRingerMode(ringerMode);
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index cdeb563..682560a 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -424,6 +424,12 @@ public class AudioService extends IAudioService.Stub {
final ContentResolver cr = mContentResolver;
mRingerMode = System.getInt(cr, System.MODE_RINGER, AudioManager.RINGER_MODE_NORMAL);
+ // sanity check in case the settings are restored from a device with incompatible
+ // ringer modes
+ if (!AudioManager.isValidRingerMode(mRingerMode)) {
+ mRingerMode = AudioManager.RINGER_MODE_NORMAL;
+ System.putInt(cr, System.MODE_RINGER, mRingerMode);
+ }
mVibrateSetting = System.getInt(cr, System.VIBRATE_ON, 0);
diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp
index 178039c..ed6e3c7 100644
--- a/media/libmedia/mediaplayer.cpp
+++ b/media/libmedia/mediaplayer.cpp
@@ -84,6 +84,8 @@ void MediaPlayer::disconnect()
if (p != 0) {
p->disconnect();
}
+
+ disconnectNativeWindow();
}
// always call with lock held
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index d4d07b2..174ec92 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -445,6 +445,13 @@ status_t ACodec::allocateOutputBuffersFromNativeWindow() {
return err;
}
+ err = native_window_set_scaling_mode(mNativeWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+
+ if (err != OK) {
+ return err;
+ }
+
err = native_window_set_buffers_geometry(
mNativeWindow.get(),
def.format.video.nFrameWidth,
diff --git a/media/libstagefright/ESDS.cpp b/media/libstagefright/ESDS.cpp
index b7c8e0c..1f7ee25 100644
--- a/media/libstagefright/ESDS.cpp
+++ b/media/libstagefright/ESDS.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ESDS"
+#include <utils/Log.h>
+
#include "include/ESDS.h"
#include <string.h>
@@ -87,6 +91,8 @@ status_t ESDS::skipDescriptorHeader(
}
while (more);
+ LOGV("tag=0x%02x data_size=%d", *tag, *data_size);
+
if (*data_size > size) {
return ERROR_MALFORMED;
}
@@ -146,8 +152,20 @@ status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
if (OCRstreamFlag) {
offset += 2;
size -= 2;
+
+ if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
+ && offset - 2 < size
+ && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
+ // Content found "in the wild" had OCRstreamFlag set but was
+ // missing OCR_ES_Id, the decoder config descriptor immediately
+ // followed instead.
+ offset -= 2;
+ size += 2;
+
+ LOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
+ }
}
-
+
if (offset >= size) {
return ERROR_MALFORMED;
}
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 4f8336e..7bcbdcf 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1765,6 +1765,13 @@ status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
return err;
}
+ err = native_window_set_scaling_mode(mNativeWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+
+ if (err != OK) {
+ return err;
+ }
+
err = native_window_set_buffers_geometry(
mNativeWindow.get(),
def.format.video.nFrameWidth,
diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
index a4ca32d..3246021 100644
--- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp
+++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp
@@ -93,6 +93,11 @@ SoftwareRenderer::SoftwareRenderer(
GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
| GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
+ CHECK_EQ(0,
+ native_window_set_scaling_mode(
+ mNativeWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW));
+
// Width must be multiple of 32???
CHECK_EQ(0, native_window_set_buffers_geometry(
mNativeWindow.get(),
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 73b3d5b..90d64ba 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -785,7 +785,10 @@ status_t LiveSession::decryptBuffer(
keySource->setUID(mUID);
}
- status_t err = keySource->connect(keyURI.c_str());
+ status_t err =
+ keySource->connect(
+ keyURI.c_str(),
+ mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);
if (err == OK) {
size_t offset = 0;
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 123fbf8..9df9f59 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -106,21 +106,38 @@ static bool MakeURL(const char *baseURL, const char *url, AString *out) {
return true;
}
- size_t n = strlen(baseURL);
- if (baseURL[n - 1] == '/') {
- out->setTo(baseURL);
- out->append(url);
- } else {
- const char *slashPos = strrchr(baseURL, '/');
+ if (url[0] == '/') {
+ // URL is an absolute path.
+
+ char *protocolEnd = strstr(baseURL, "//") + 2;
+ char *pathStart = strchr(protocolEnd, '/');
- if (slashPos > &baseURL[6]) {
- out->setTo(baseURL, slashPos - baseURL);
+ if (pathStart != NULL) {
+ out->setTo(baseURL, pathStart - baseURL);
} else {
out->setTo(baseURL);
}
- out->append("/");
out->append(url);
+ } else {
+ // URL is a relative path
+
+ size_t n = strlen(baseURL);
+ if (baseURL[n - 1] == '/') {
+ out->setTo(baseURL);
+ out->append(url);
+ } else {
+ const char *slashPos = strrchr(baseURL, '/');
+
+ if (slashPos > &baseURL[6]) {
+ out->setTo(baseURL, slashPos - baseURL);
+ } else {
+ out->setTo(baseURL);
+ }
+
+ out->append("/");
+ out->append(url);
+ }
}
LOGV("base:'%s', url:'%s' => '%s'", baseURL, url, out->c_str());
diff --git a/native/android/native_window.cpp b/native/android/native_window.cpp
index 5c016c4..36fc9bf 100644
--- a/native/android/native_window.cpp
+++ b/native/android/native_window.cpp
@@ -76,7 +76,15 @@ int32_t ANativeWindow_getFormat(ANativeWindow* window) {
int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window, int32_t width,
int32_t height, int32_t format) {
- return native_window_set_buffers_geometry(window, width, height, format);
+ int32_t err = native_window_set_buffers_geometry(window, width, height, format);
+ if (!err) {
+ int mode = NATIVE_WINDOW_SCALING_MODE_FREEZE;
+ if (width && height) {
+ mode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
+ }
+ err = native_window_set_scaling_mode(window, mode);
+ }
+ return err;
}
int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
diff --git a/opengl/tests/gl2_copyTexImage/Android.mk b/opengl/tests/gl2_copyTexImage/Android.mk
new file mode 100644
index 0000000..bef1f90
--- /dev/null
+++ b/opengl/tests/gl2_copyTexImage/Android.mk
@@ -0,0 +1,19 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ gl2_copyTexImage.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libEGL \
+ libGLESv2 \
+ libui
+
+LOCAL_MODULE:= test-opengl-gl2_copyTexImage
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -DGL_GLEXT_PROTOTYPES
+
+include $(BUILD_EXECUTABLE)
diff --git a/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp b/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp
new file mode 100644
index 0000000..c2bfdec
--- /dev/null
+++ b/opengl/tests/gl2_copyTexImage/gl2_copyTexImage.cpp
@@ -0,0 +1,467 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sched.h>
+#include <sys/resource.h>
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
+#include <utils/Timers.h>
+
+#include <ui/FramebufferNativeWindow.h>
+#include <ui/EGLUtils.h>
+
+using namespace android;
+
+static void printGLString(const char *name, GLenum s) {
+ // fprintf(stderr, "printGLString %s, %d\n", name, s);
+ const char *v = (const char *) glGetString(s);
+ // int error = glGetError();
+ // fprintf(stderr, "glGetError() = %d, result of glGetString = %x\n", error,
+ // (unsigned int) v);
+ // if ((v < (const char*) 0) || (v > (const char*) 0x10000))
+ // fprintf(stderr, "GL %s = %s\n", name, v);
+ // else
+ // fprintf(stderr, "GL %s = (null) 0x%08x\n", name, (unsigned int) v);
+ fprintf(stderr, "GL %s = %s\n", name, v);
+}
+
+static void checkEglError(const char* op, EGLBoolean returnVal = EGL_TRUE) {
+ if (returnVal != EGL_TRUE) {
+ fprintf(stderr, "%s() returned %d\n", op, returnVal);
+ }
+
+ for (EGLint error = eglGetError(); error != EGL_SUCCESS; error
+ = eglGetError()) {
+ fprintf(stderr, "after %s() eglError %s (0x%x)\n", op, EGLUtils::strerror(error),
+ error);
+ }
+}
+
+static void checkGlError(const char* op) {
+ for (GLint error = glGetError(); error; error
+ = glGetError()) {
+ fprintf(stderr, "after %s() glError (0x%x)\n", op, error);
+ }
+}
+
+static const char gVertexShader[] = "attribute vec4 vPosition;\n"
+ "void main() {\n"
+ " gl_Position = vPosition;\n"
+ "}\n";
+
+static const char gFragmentShader[] = "precision mediump float;\n"
+ "void main() {\n"
+ " gl_FragColor = vec4(0.0, 1.0, 0.0, 0.5);\n"
+ "}\n";
+
+GLuint loadShader(GLenum shaderType, const char* pSource) {
+ GLuint shader = glCreateShader(shaderType);
+ if (shader) {
+ glShaderSource(shader, 1, &pSource, NULL);
+ glCompileShader(shader);
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+ if (!compiled) {
+ GLint infoLen = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
+ if (infoLen) {
+ char* buf = (char*) malloc(infoLen);
+ if (buf) {
+ glGetShaderInfoLog(shader, infoLen, NULL, buf);
+ fprintf(stderr, "Could not compile shader %d:\n%s\n",
+ shaderType, buf);
+ free(buf);
+ }
+ glDeleteShader(shader);
+ shader = 0;
+ }
+ }
+ }
+ return shader;
+}
+
+GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
+ GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
+ if (!vertexShader) {
+ return 0;
+ }
+
+ GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
+ if (!pixelShader) {
+ return 0;
+ }
+
+ GLuint program = glCreateProgram();
+ if (program) {
+ glAttachShader(program, vertexShader);
+ checkGlError("glAttachShader");
+ glAttachShader(program, pixelShader);
+ checkGlError("glAttachShader");
+ glLinkProgram(program);
+ GLint linkStatus = GL_FALSE;
+ glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+ if (linkStatus != GL_TRUE) {
+ GLint bufLength = 0;
+ glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
+ if (bufLength) {
+ char* buf = (char*) malloc(bufLength);
+ if (buf) {
+ glGetProgramInfoLog(program, bufLength, NULL, buf);
+ fprintf(stderr, "Could not link program:\n%s\n", buf);
+ free(buf);
+ }
+ }
+ glDeleteProgram(program);
+ program = 0;
+ }
+ }
+ return program;
+}
+
+GLuint gProgram;
+GLuint gTextureProgram;
+GLuint gvPositionHandle;
+GLuint gvTexturePositionHandle;
+GLuint gvTextureTexCoordsHandle;
+GLuint gvTextureSamplerHandle;
+GLuint gFbo;
+GLuint gTexture;
+GLuint gBufferTexture;
+
+static const char gSimpleVS[] =
+ "attribute vec4 position;\n"
+ "attribute vec2 texCoords;\n"
+ "varying vec2 outTexCoords;\n"
+ "\nvoid main(void) {\n"
+ " outTexCoords = texCoords;\n"
+ " gl_Position = position;\n"
+ "}\n\n";
+static const char gSimpleFS[] =
+ "precision mediump float;\n\n"
+ "varying vec2 outTexCoords;\n"
+ "uniform sampler2D texture;\n"
+ "\nvoid main(void) {\n"
+ " gl_FragColor = texture2D(texture, outTexCoords);\n"
+ "}\n\n";
+
+bool setupGraphics(int w, int h) {
+ gProgram = createProgram(gVertexShader, gFragmentShader);
+ if (!gProgram) {
+ return false;
+ }
+ gvPositionHandle = glGetAttribLocation(gProgram, "vPosition");
+ checkGlError("glGetAttribLocation");
+ fprintf(stderr, "glGetAttribLocation(\"vPosition\") = %d\n", gvPositionHandle);
+
+ gTextureProgram = createProgram(gSimpleVS, gSimpleFS);
+ if (!gTextureProgram) {
+ return false;
+ }
+ gvTexturePositionHandle = glGetAttribLocation(gTextureProgram, "position");
+ checkGlError("glGetAttribLocation");
+ gvTextureTexCoordsHandle = glGetAttribLocation(gTextureProgram, "texCoords");
+ checkGlError("glGetAttribLocation");
+ gvTextureSamplerHandle = glGetUniformLocation(gTextureProgram, "texture");
+ checkGlError("glGetAttribLocation");
+
+ glActiveTexture(GL_TEXTURE0);
+
+ glGenTextures(1, &gTexture);
+ glBindTexture(GL_TEXTURE_2D, gTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glGenTextures(1, &gBufferTexture);
+ glBindTexture(GL_TEXTURE_2D, gBufferTexture);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ glGenFramebuffers(1, &gFbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, gFbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gTexture, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ glViewport(0, 0, w, h);
+ checkGlError("glViewport");
+ return true;
+}
+
+const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
+ 0.5f, -0.5f };
+
+const GLint FLOAT_SIZE_BYTES = 4;
+const GLint TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
+const GLfloat gTriangleVerticesData[] = {
+ // X, Y, Z, U, V
+ -1.0f, -1.0f, 0, 0.f, 0.f,
+ 1.0f, -1.0f, 0, 1.f, 0.f,
+ -1.0f, 1.0f, 0, 0.f, 1.f,
+ 1.0f, 1.0f, 0, 1.f, 1.f,
+};
+
+void renderFrame(GLint w, GLint h) {
+ glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
+ checkGlError("glClearColor");
+ glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
+ checkGlError("glClear");
+
+ // Bind FBO and draw into it
+ glBindFramebuffer(GL_FRAMEBUFFER, gFbo);
+ checkGlError("glBindFramebuffer");
+
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ checkGlError("glClearColor");
+ glClear(GL_COLOR_BUFFER_BIT);
+ checkGlError("glClear");
+
+ glUseProgram(gProgram);
+ checkGlError("glUseProgram");
+
+ glVertexAttribPointer(gvPositionHandle, 2, GL_FLOAT, GL_FALSE, 0, gTriangleVertices);
+ checkGlError("glVertexAttribPointer");
+ glEnableVertexAttribArray(gvPositionHandle);
+ checkGlError("glEnableVertexAttribArray");
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ checkGlError("glDrawArrays");
+
+ // Copy content of FBO into a texture
+ glBindTexture(GL_TEXTURE_2D, gBufferTexture);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, w / 2, h / 2);
+ checkGlError("glCopyTexSubImage2D");
+
+ // Back to the display
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ checkGlError("glBindFramebuffer");
+
+ // Draw copied content on the screen
+ glUseProgram(gTextureProgram);
+ checkGlError("glUseProgram");
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glVertexAttribPointer(gvTexturePositionHandle, 3, GL_FLOAT, GL_FALSE,
+ TRIANGLE_VERTICES_DATA_STRIDE_BYTES, gTriangleVerticesData);
+ checkGlError("glVertexAttribPointer");
+ glVertexAttribPointer(gvTextureTexCoordsHandle, 2, GL_FLOAT, GL_FALSE,
+ TRIANGLE_VERTICES_DATA_STRIDE_BYTES, &gTriangleVerticesData[3]);
+ checkGlError("glVertexAttribPointer");
+ glEnableVertexAttribArray(gvTexturePositionHandle);
+ glEnableVertexAttribArray(gvTextureTexCoordsHandle);
+ checkGlError("glEnableVertexAttribArray");
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ checkGlError("glDrawArrays");
+}
+
+void printEGLConfiguration(EGLDisplay dpy, EGLConfig config) {
+
+#define X(VAL) {VAL, #VAL}
+ struct {EGLint attribute; const char* name;} names[] = {
+ X(EGL_BUFFER_SIZE),
+ X(EGL_ALPHA_SIZE),
+ X(EGL_BLUE_SIZE),
+ X(EGL_GREEN_SIZE),
+ X(EGL_RED_SIZE),
+ X(EGL_DEPTH_SIZE),
+ X(EGL_STENCIL_SIZE),
+ X(EGL_CONFIG_CAVEAT),
+ X(EGL_CONFIG_ID),
+ X(EGL_LEVEL),
+ X(EGL_MAX_PBUFFER_HEIGHT),
+ X(EGL_MAX_PBUFFER_PIXELS),
+ X(EGL_MAX_PBUFFER_WIDTH),
+ X(EGL_NATIVE_RENDERABLE),
+ X(EGL_NATIVE_VISUAL_ID),
+ X(EGL_NATIVE_VISUAL_TYPE),
+ X(EGL_SAMPLES),
+ X(EGL_SAMPLE_BUFFERS),
+ X(EGL_SURFACE_TYPE),
+ X(EGL_TRANSPARENT_TYPE),
+ X(EGL_TRANSPARENT_RED_VALUE),
+ X(EGL_TRANSPARENT_GREEN_VALUE),
+ X(EGL_TRANSPARENT_BLUE_VALUE),
+ X(EGL_BIND_TO_TEXTURE_RGB),
+ X(EGL_BIND_TO_TEXTURE_RGBA),
+ X(EGL_MIN_SWAP_INTERVAL),
+ X(EGL_MAX_SWAP_INTERVAL),
+ X(EGL_LUMINANCE_SIZE),
+ X(EGL_ALPHA_MASK_SIZE),
+ X(EGL_COLOR_BUFFER_TYPE),
+ X(EGL_RENDERABLE_TYPE),
+ X(EGL_CONFORMANT),
+ };
+#undef X
+
+ for (size_t j = 0; j < sizeof(names) / sizeof(names[0]); j++) {
+ EGLint value = -1;
+ EGLint returnVal = eglGetConfigAttrib(dpy, config, names[j].attribute, &value);
+ EGLint error = eglGetError();
+ if (returnVal && error == EGL_SUCCESS) {
+ printf(" %s: ", names[j].name);
+ printf("%d (0x%x)", value, value);
+ }
+ }
+ printf("\n");
+}
+
+int printEGLConfigurations(EGLDisplay dpy) {
+ EGLint numConfig = 0;
+ EGLint returnVal = eglGetConfigs(dpy, NULL, 0, &numConfig);
+ checkEglError("eglGetConfigs", returnVal);
+ if (!returnVal) {
+ return false;
+ }
+
+ printf("Number of EGL configuration: %d\n", numConfig);
+
+ EGLConfig* configs = (EGLConfig*) malloc(sizeof(EGLConfig) * numConfig);
+ if (! configs) {
+ printf("Could not allocate configs.\n");
+ return false;
+ }
+
+ returnVal = eglGetConfigs(dpy, configs, numConfig, &numConfig);
+ checkEglError("eglGetConfigs", returnVal);
+ if (!returnVal) {
+ free(configs);
+ return false;
+ }
+
+ for(int i = 0; i < numConfig; i++) {
+ printf("Configuration %d\n", i);
+ printEGLConfiguration(dpy, configs[i]);
+ }
+
+ free(configs);
+ return true;
+}
+
+int main(int argc, char** argv) {
+ EGLBoolean returnValue;
+ EGLConfig myConfig = {0};
+
+ EGLint context_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ EGLint s_configAttribs[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_NONE };
+ EGLint majorVersion;
+ EGLint minorVersion;
+ EGLContext context;
+ EGLSurface surface;
+ EGLint w, h;
+
+ EGLDisplay dpy;
+
+ checkEglError("<init>");
+ dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ checkEglError("eglGetDisplay");
+ if (dpy == EGL_NO_DISPLAY) {
+ printf("eglGetDisplay returned EGL_NO_DISPLAY.\n");
+ return 0;
+ }
+
+ returnValue = eglInitialize(dpy, &majorVersion, &minorVersion);
+ checkEglError("eglInitialize", returnValue);
+ fprintf(stderr, "EGL version %d.%d\n", majorVersion, minorVersion);
+ if (returnValue != EGL_TRUE) {
+ printf("eglInitialize failed\n");
+ return 0;
+ }
+
+ if (!printEGLConfigurations(dpy)) {
+ printf("printEGLConfigurations failed\n");
+ return 0;
+ }
+
+ checkEglError("printEGLConfigurations");
+
+ EGLNativeWindowType window = android_createDisplaySurface();
+ EGLint numConfigs = -1, n = 0;
+ eglChooseConfig(dpy, s_configAttribs, 0, 0, &numConfigs);
+ if (numConfigs) {
+ EGLConfig* const configs = new EGLConfig[numConfigs];
+ eglChooseConfig(dpy, s_configAttribs, configs, numConfigs, &n);
+ myConfig = configs[0];
+ delete[] configs;
+ }
+
+ checkEglError("EGLUtils::selectConfigForNativeWindow");
+
+ printf("Chose this configuration:\n");
+ printEGLConfiguration(dpy, myConfig);
+
+ surface = eglCreateWindowSurface(dpy, myConfig, window, NULL);
+ checkEglError("eglCreateWindowSurface");
+ if (surface == EGL_NO_SURFACE) {
+ printf("gelCreateWindowSurface failed.\n");
+ return 0;
+ }
+
+ context = eglCreateContext(dpy, myConfig, EGL_NO_CONTEXT, context_attribs);
+ checkEglError("eglCreateContext");
+ if (context == EGL_NO_CONTEXT) {
+ printf("eglCreateContext failed\n");
+ return 0;
+ }
+ returnValue = eglMakeCurrent(dpy, surface, surface, context);
+ checkEglError("eglMakeCurrent", returnValue);
+ if (returnValue != EGL_TRUE) {
+ return 0;
+ }
+ eglQuerySurface(dpy, surface, EGL_WIDTH, &w);
+ checkEglError("eglQuerySurface");
+ eglQuerySurface(dpy, surface, EGL_HEIGHT, &h);
+ checkEglError("eglQuerySurface");
+ GLint dim = w < h ? w : h;
+
+ fprintf(stderr, "Window dimensions: %d x %d\n", w, h);
+
+ printGLString("Version", GL_VERSION);
+ printGLString("Vendor", GL_VENDOR);
+ printGLString("Renderer", GL_RENDERER);
+ printGLString("Extensions", GL_EXTENSIONS);
+
+ if(!setupGraphics(w, h)) {
+ fprintf(stderr, "Could not set up graphics.\n");
+ return 0;
+ }
+
+ for (;;) {
+ renderFrame(w, h);
+ eglSwapBuffers(dpy, surface);
+ checkEglError("eglSwapBuffers");
+ }
+
+ return 0;
+}
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 981fb24..b4d2a14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
@@ -236,6 +236,7 @@ public class NotificationRowLayout extends ViewGroup {
@Override
public void onAnimationEnd(Animator animation) {
mAppearingViews.remove(childF);
+ requestLayout(); // pick up any final changes in position
}
});
a.start();
@@ -274,6 +275,7 @@ public class NotificationRowLayout extends ViewGroup {
NotificationRowLayout.super.removeView(childF);
childF.setAlpha(1f);
mDisappearingViews.remove(childF);
+ requestLayout(); // pick up any final changes in position
}
});
@@ -372,7 +374,7 @@ public class NotificationRowLayout extends ViewGroup {
final int width = right - left;
final int height = bottom - top;
- //if (DEBUG) Slog.d(TAG, "onLayout: height=" + height);
+ if (DEBUG) Slog.d(TAG, "onLayout: height=" + height);
final int count = getChildCount();
int y = 0;
@@ -381,20 +383,22 @@ public class NotificationRowLayout extends ViewGroup {
if (child.getVisibility() == GONE) {
continue;
}
-// final int thisRowHeight = (int)(
-// ((mAppearingViews.contains(child) || mDisappearingViews.contains(child))
-// ? child.getScaleY()
-// : 1.0f)
-// * mRowHeight);
final int thisRowHeight = (int)(child.getAlpha() * mRowHeight);
-// child.layout(0, y, width, y + thisRowHeight);
- child.layout(0, y, width, y + mRowHeight);
+ if (DEBUG) {
+ Slog.d(TAG, String.format(
+ "laying out child #%d: (0, %d, %d, %d) h=%d",
+ i, y, width, y + thisRowHeight, thisRowHeight));
+ }
+ child.layout(0, y, width, y + thisRowHeight);
y += thisRowHeight;
}
+ if (DEBUG) {
+ Slog.d(TAG, "onLayout: final y=" + y);
+ }
}
public void setForcedHeight(int h) {
- //if (DEBUG) Slog.d(TAG, "forcedHeight: " + h);
+ if (DEBUG) Slog.d(TAG, "forcedHeight: " + h);
if (h != mHeight) {
mHeight = h;
requestLayout();
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index 0eff776..96b26e7 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -458,6 +458,17 @@ status_t CameraService::Client::connect(const sp<ICameraClient>& client) {
return NO_ERROR;
}
+static void disconnectWindow(const sp<ANativeWindow>& window) {
+ if (window != 0) {
+ status_t result = native_window_disconnect(window.get(),
+ NATIVE_WINDOW_API_CAMERA);
+ if (result != NO_ERROR) {
+ LOGW("native_window_disconnect failed: %s (%d)", strerror(-result),
+ result);
+ }
+ }
+}
+
void CameraService::Client::disconnect() {
int callingPid = getCallingPid();
LOG1("disconnect E (pid %d)", callingPid);
@@ -489,6 +500,7 @@ void CameraService::Client::disconnect() {
// Release the held ANativeWindow resources.
if (mPreviewWindow != 0) {
+ disconnectWindow(mPreviewWindow);
mPreviewWindow = 0;
mHardware->setPreviewWindow(mPreviewWindow);
}
@@ -502,17 +514,6 @@ void CameraService::Client::disconnect() {
// ----------------------------------------------------------------------------
-static void disconnectWindow(const sp<ANativeWindow>& window) {
- if (window != 0) {
- status_t result = native_window_disconnect(window.get(),
- NATIVE_WINDOW_API_CAMERA);
- if (result != NO_ERROR) {
- LOGW("native_window_disconnect failed: %s (%d)", strerror(-result),
- result);
- }
- }
-}
-
status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
const sp<ANativeWindow>& window) {
Mutex::Autolock lock(mLock);
@@ -536,6 +537,8 @@ status_t CameraService::Client::setPreviewWindow(const sp<IBinder>& binder,
// If preview has been already started, register preview buffers now.
if (mHardware->previewEnabled()) {
if (window != 0) {
+ native_window_set_scaling_mode(window.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
native_window_set_buffers_transform(window.get(), mOrientation);
result = mHardware->setPreviewWindow(window);
}
@@ -642,6 +645,8 @@ status_t CameraService::Client::startPreviewMode() {
}
if (mPreviewWindow != 0) {
+ native_window_set_scaling_mode(mPreviewWindow.get(),
+ NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
native_window_set_buffers_transform(mPreviewWindow.get(),
mOrientation);
}
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java
index 0b15221..438883e 100644
--- a/services/java/com/android/server/AppWidgetService.java
+++ b/services/java/com/android/server/AppWidgetService.java
@@ -1022,6 +1022,12 @@ class AppWidgetService extends IAppWidgetService.Stub
info.minWidth = value != null ? value.data : 0;
value = sa.peekValue(com.android.internal.R.styleable.AppWidgetProviderInfo_minHeight);
info.minHeight = value != null ? value.data : 0;
+ value = sa.peekValue(
+ com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeWidth);
+ info.minResizeWidth = value != null ? value.data : info.minWidth;
+ value = sa.peekValue(
+ com.android.internal.R.styleable.AppWidgetProviderInfo_minResizeHeight);
+ info.minResizeHeight = value != null ? value.data : info.minHeight;
info.updatePeriodMillis = sa.getInt(
com.android.internal.R.styleable.AppWidgetProviderInfo_updatePeriodMillis, 0);
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 55c92e8..b78424b 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -248,7 +248,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// list of DeathRecipients used to make sure features are turned off when
// a process dies
- private List mFeatureUsers;
+ private List<FeatureUser> mFeatureUsers;
private boolean mSystemReady;
private Intent mInitialBroadcast;
@@ -436,7 +436,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetRequestersPids[i] = new ArrayList();
}
- mFeatureUsers = new ArrayList();
+ mFeatureUsers = new ArrayList<FeatureUser>();
mNumDnsEntries = 0;
@@ -484,6 +484,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
continue;
}
mCurrentLinkProperties[netType] = null;
+ if (mNetConfigs[netType].isDefault()) mNetTrackers[netType].reconnect();
}
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
@@ -794,6 +795,20 @@ public class ConnectivityService extends IConnectivityManager.Stub {
stopUsingNetworkFeature(this, false);
}
+ public boolean isSameUser(FeatureUser u) {
+ if (u == null) return false;
+
+ return isSameUser(u.mPid, u.mUid, u.mNetworkType, u.mFeature);
+ }
+
+ public boolean isSameUser(int pid, int uid, int networkType, String feature) {
+ if ((mPid == pid) && (mUid == uid) && (mNetworkType == networkType) &&
+ TextUtils.equals(mFeature, feature)) {
+ return true;
+ }
+ return false;
+ }
+
public String toString() {
return "FeatureUser("+mNetworkType+","+mFeature+","+mPid+","+mUid+"), created " +
(System.currentTimeMillis() - mCreateTime) + " mSec ago";
@@ -844,16 +859,29 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
+
synchronized(this) {
- mFeatureUsers.add(f);
+ boolean addToList = true;
+ if (restoreTimer < 0) {
+ // In case there is no timer is specified for the feature,
+ // make sure we don't add duplicate entry with the same request.
+ for (FeatureUser u : mFeatureUsers) {
+ if (u.isSameUser(f)) {
+ // Duplicate user is found. Do not add.
+ addToList = false;
+ break;
+ }
+ }
+ }
+
+ if (addToList) mFeatureUsers.add(f);
if (!mNetRequestersPids[usedNetworkType].contains(currentPid)) {
// this gets used for per-pid dns when connected
mNetRequestersPids[usedNetworkType].add(currentPid);
}
}
- int restoreTimer = getRestoreDefaultNetworkDelay(usedNetworkType);
-
if (restoreTimer >= 0) {
mHandler.sendMessageDelayed(
mHandler.obtainMessage(EVENT_RESTORE_DEFAULT_NETWORK, f), restoreTimer);
@@ -903,11 +931,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
boolean found = false;
synchronized(this) {
- for (int i = 0; i < mFeatureUsers.size() ; i++) {
- u = (FeatureUser)mFeatureUsers.get(i);
- if (uid == u.mUid && pid == u.mPid &&
- networkType == u.mNetworkType &&
- TextUtils.equals(feature, u.mFeature)) {
+ for (FeatureUser x : mFeatureUsers) {
+ if (x.isSameUser(pid, uid, networkType, feature)) {
+ u = x;
found = true;
break;
}
@@ -959,11 +985,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// do not pay attention to duplicate requests - in effect the
// API does not refcount and a single stop will counter multiple starts.
if (ignoreDups == false) {
- for (int i = 0; i < mFeatureUsers.size() ; i++) {
- FeatureUser x = (FeatureUser)mFeatureUsers.get(i);
- if (x.mUid == u.mUid && x.mPid == u.mPid &&
- x.mNetworkType == u.mNetworkType &&
- TextUtils.equals(x.mFeature, u.mFeature)) {
+ for (FeatureUser x : mFeatureUsers) {
+ if (x.isSameUser(u)) {
if (DBG) log("ignoring stopUsingNetworkFeature as dup is found");
return 1;
}
diff --git a/services/java/com/android/server/MasterClearReceiver.java b/services/java/com/android/server/MasterClearReceiver.java
index bdb5a24..86f57d1 100644
--- a/services/java/com/android/server/MasterClearReceiver.java
+++ b/services/java/com/android/server/MasterClearReceiver.java
@@ -43,11 +43,7 @@ public class MasterClearReceiver extends BroadcastReceiver {
@Override
public void run() {
try {
- if (intent.hasExtra("enableEFS")) {
- RecoverySystem.rebootToggleEFS(context, intent.getBooleanExtra("enableEFS", false));
- } else {
- RecoverySystem.rebootWipeUserData(context);
- }
+ RecoverySystem.rebootWipeUserData(context);
Log.wtf(TAG, "Still running after master clear?!");
} catch (IOException e) {
Slog.e(TAG, "Can't perform master clear/factory reset", e);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 94af46d..0924b86 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -2439,7 +2439,7 @@ public final class ActivityManagerService extends ActivityManagerNative
r.mayFreezeScreenLocked(r.app) ? r : null);
if (config != null) {
r.frozenBeforeDestroy = true;
- if (!updateConfigurationLocked(config, r)) {
+ if (!updateConfigurationLocked(config, r, false)) {
mMainStack.resumeTopActivityLocked(null);
}
}
@@ -12398,6 +12398,22 @@ public final class ActivityManagerService extends ActivityManagerNative
return ci;
}
+ public void updatePersistentConfiguration(Configuration values) {
+ enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
+ "updateConfiguration()");
+ enforceCallingPermission(android.Manifest.permission.WRITE_SETTINGS,
+ "updateConfiguration()");
+ if (values == null) {
+ throw new NullPointerException("Configuration must not be null");
+ }
+
+ synchronized(this) {
+ final long origId = Binder.clearCallingIdentity();
+ updateConfigurationLocked(values, null, true);
+ Binder.restoreCallingIdentity(origId);
+ }
+ }
+
public void updateConfiguration(Configuration values) {
enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
@@ -12409,7 +12425,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
final long origId = Binder.clearCallingIdentity();
- updateConfigurationLocked(values, null);
+ if (values != null) {
+ Settings.System.clearConfiguration(values);
+ }
+ updateConfigurationLocked(values, null, false);
Binder.restoreCallingIdentity(origId);
}
}
@@ -12420,9 +12439,10 @@ public final class ActivityManagerService extends ActivityManagerNative
* configuration. Returns true if the activity has been left running, or
* false if <var>starting</var> is being destroyed to match the new
* configuration.
+ * @param persistent TODO
*/
public boolean updateConfigurationLocked(Configuration values,
- ActivityRecord starting) {
+ ActivityRecord starting, boolean persistent) {
int changes = 0;
boolean kept = true;
@@ -12465,7 +12485,7 @@ public final class ActivityManagerService extends ActivityManagerNative
// code is executed.
mSystemThread.applyConfigurationToResources(newConfig);
- if (Settings.System.hasInterestingConfigurationChanges(changes)) {
+ if (persistent && Settings.System.hasInterestingConfigurationChanges(changes)) {
Message msg = mHandler.obtainMessage(UPDATE_CONFIGURATION_MSG);
msg.obj = new Configuration(mConfiguration);
mHandler.sendMessage(msg);
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 93d8164..0d89081 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -518,7 +518,7 @@ final class ActivityStack {
Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
mService.mConfiguration,
r.mayFreezeScreenLocked(app) ? r : null);
- mService.updateConfigurationLocked(config, r);
+ mService.updateConfigurationLocked(config, r, false);
}
r.app = app;
@@ -1424,7 +1424,7 @@ final class ActivityStack {
if (config != null) {
next.frozenBeforeDestroy = true;
}
- updated = mService.updateConfigurationLocked(config, next);
+ updated = mService.updateConfigurationLocked(config, next, false);
}
}
if (!updated) {
@@ -2817,7 +2817,7 @@ final class ActivityStack {
mConfigWillChange = false;
if (DEBUG_CONFIGURATION) Slog.v(TAG,
"Updating to new configuration after starting activity.");
- mService.updateConfigurationLocked(config, null);
+ mService.updateConfigurationLocked(config, null, false);
}
Binder.restoreCallingIdentity(origId);
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 5ed7988..f270003 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1093,8 +1093,7 @@ final class Settings {
serializer.attribute(null, "uidError", "true");
}
if (pkg.enabled != COMPONENT_ENABLED_STATE_DEFAULT) {
- serializer.attribute(null, "enabled",
- pkg.enabled == COMPONENT_ENABLED_STATE_ENABLED ? "true" : "false");
+ serializer.attribute(null, "enabled", Integer.toString(pkg.enabled));
}
if (pkg.installStatus == PackageSettingBase.PKG_INSTALL_INCOMPLETE) {
serializer.attribute(null, "installStatus", "false");
@@ -1644,17 +1643,21 @@ final class Settings {
packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
final String enabledStr = parser.getAttributeValue(null, "enabled");
if (enabledStr != null) {
- if (enabledStr.equalsIgnoreCase("true")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
- } else if (enabledStr.equalsIgnoreCase("false")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
- } else if (enabledStr.equalsIgnoreCase("default")) {
- packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
- } else {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Error in package manager settings: package " + name
- + " has bad enabled value: " + idStr + " at "
- + parser.getPositionDescription());
+ try {
+ packageSetting.enabled = Integer.parseInt(enabledStr);
+ } catch (NumberFormatException e) {
+ if (enabledStr.equalsIgnoreCase("true")) {
+ packageSetting.enabled = COMPONENT_ENABLED_STATE_ENABLED;
+ } else if (enabledStr.equalsIgnoreCase("false")) {
+ packageSetting.enabled = COMPONENT_ENABLED_STATE_DISABLED;
+ } else if (enabledStr.equalsIgnoreCase("default")) {
+ packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
+ } else {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: package " + name
+ + " has bad enabled value: " + idStr + " at "
+ + parser.getPositionDescription());
+ }
}
} else {
packageSetting.enabled = COMPONENT_ENABLED_STATE_DEFAULT;
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f3b6c4d..e0268fa 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -44,10 +44,6 @@
namespace android {
-template <typename T> inline T min(T a, T b) {
- return a<b ? a : b;
-}
-
// ---------------------------------------------------------------------------
Layer::Layer(SurfaceFlinger* flinger,
@@ -56,14 +52,14 @@ Layer::Layer(SurfaceFlinger* flinger,
mTextureName(-1U),
mQueuedFrames(0),
mCurrentTransform(0),
+ mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
mCurrentOpacity(true),
mFormat(PIXEL_FORMAT_NONE),
mGLExtensions(GLExtensions::getInstance()),
mOpaqueLayer(true),
mNeedsDithering(false),
mSecure(false),
- mProtectedByApp(false),
- mFixedSize(false)
+ mProtectedByApp(false)
{
mCurrentCrop.makeInvalid();
glGenTextures(1, &mTextureName);
@@ -400,14 +396,7 @@ uint32_t Layer::doTransaction(uint32_t flags)
}
bool Layer::isFixedSize() const {
- Mutex::Autolock _l(mLock);
- return mFixedSize;
-}
-
-void Layer::setFixedSize(bool fixedSize)
-{
- Mutex::Autolock _l(mLock);
- mFixedSize = fixedSize;
+ return mCurrentScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
}
bool Layer::isCropped() const {
@@ -437,9 +426,14 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
const Rect crop(mSurfaceTexture->getCurrentCrop());
const uint32_t transform(mSurfaceTexture->getCurrentTransform());
- if ((crop != mCurrentCrop) || (transform != mCurrentTransform)) {
+ const uint32_t scalingMode(mSurfaceTexture->getCurrentScalingMode());
+ if ((crop != mCurrentCrop) ||
+ (transform != mCurrentTransform) ||
+ (scalingMode != mCurrentScalingMode))
+ {
mCurrentCrop = crop;
mCurrentTransform = transform;
+ mCurrentScalingMode = scalingMode;
mFlinger->invalidateHwcGeometry();
}
@@ -459,13 +453,22 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// FIXME: mPostedDirtyRegion = dirty & bounds
mPostedDirtyRegion.set(front.w, front.h);
- sp<GraphicBuffer> newFrontBuffer(mActiveBuffer);
- if ((newFrontBuffer->getWidth() == front.requested_w &&
- newFrontBuffer->getHeight() == front.requested_h) ||
- isFixedSize())
+
+ if ((front.w != front.requested_w) ||
+ (front.h != front.requested_h))
{
- if ((front.w != front.requested_w) ||
- (front.h != front.requested_h))
+ // check that we received a buffer of the right size
+ // (Take the buffer's orientation into account)
+ sp<GraphicBuffer> newFrontBuffer(mActiveBuffer);
+ uint32_t bufWidth = newFrontBuffer->getWidth();
+ uint32_t bufHeight = newFrontBuffer->getHeight();
+ if (mCurrentTransform & Transform::ROT_90) {
+ swap(bufWidth, bufHeight);
+ }
+
+ if (isFixedSize() ||
+ (bufWidth == front.requested_w &&
+ bufHeight == front.requested_h))
{
// Here we pretend the transaction happened by updating the
// current and drawing states. Drawing state is only accessed
@@ -485,10 +488,10 @@ void Layer::lockPageFlip(bool& recomputeVisibleRegions)
// recompute visible region
recomputeVisibleRegions = true;
- }
- // we now have the correct size, unfreeze the screen
- mFreezeLock.clear();
+ // we now have the correct size, unfreeze the screen
+ mFreezeLock.clear();
+ }
}
}
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e3fc13d..ddfc666 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -59,7 +59,6 @@ public:
status_t setBuffers(uint32_t w, uint32_t h,
PixelFormat format, uint32_t flags=0);
- // Set this Layer's buffers size
bool isFixedSize() const;
// LayerBase interface
@@ -88,7 +87,6 @@ private:
void onFrameQueued();
virtual sp<ISurface> createSurface();
uint32_t getEffectiveUsage(uint32_t usage) const;
- void setFixedSize(bool fixedSize);
bool isCropped() const;
static bool getOpacityForFormat(uint32_t format);
@@ -106,6 +104,7 @@ private:
GLfloat mTextureMatrix[16];
Rect mCurrentCrop;
uint32_t mCurrentTransform;
+ uint32_t mCurrentScalingMode;
bool mCurrentOpacity;
// constants
@@ -124,7 +123,6 @@ private:
// binder thread, transaction thread
mutable Mutex mLock;
- bool mFixedSize;
};
// ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceTextureLayer.cpp b/services/surfaceflinger/SurfaceTextureLayer.cpp
index 60fa965..11f61cc 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.cpp
+++ b/services/surfaceflinger/SurfaceTextureLayer.cpp
@@ -52,6 +52,20 @@ status_t SurfaceTextureLayer::setBufferCount(int bufferCount) {
return res;
}
+status_t SurfaceTextureLayer::queueBuffer(int buf, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform) {
+
+ status_t res = SurfaceTexture::queueBuffer(buf, timestamp,
+ outWidth, outHeight, outTransform);
+
+ sp<Layer> layer(mLayer.promote());
+ if (layer != NULL) {
+ *outTransform = layer->getOrientation();
+ }
+
+ return res;
+}
+
status_t SurfaceTextureLayer::dequeueBuffer(int *buf,
uint32_t w, uint32_t h, uint32_t format, uint32_t usage) {
@@ -64,9 +78,6 @@ status_t SurfaceTextureLayer::dequeueBuffer(int *buf,
//LOGD("%s, w=%u, h=%u, format=%u, usage=%08x, effectiveUsage=%08x",
// __PRETTY_FUNCTION__, w, h, format, usage, effectiveUsage);
res = SurfaceTexture::dequeueBuffer(buf, w, h, format, effectiveUsage);
- if (res == NO_ERROR) {
- layer->setFixedSize(w && h);
- }
}
return res;
}
diff --git a/services/surfaceflinger/SurfaceTextureLayer.h b/services/surfaceflinger/SurfaceTextureLayer.h
index 7faff54..29a9cbe 100644
--- a/services/surfaceflinger/SurfaceTextureLayer.h
+++ b/services/surfaceflinger/SurfaceTextureLayer.h
@@ -45,6 +45,9 @@ public:
virtual status_t setBufferCount(int bufferCount);
protected:
+ virtual status_t queueBuffer(int buf, int64_t timestamp,
+ uint32_t* outWidth, uint32_t* outHeight, uint32_t* outTransform);
+
virtual status_t dequeueBuffer(int *buf, uint32_t w, uint32_t h,
uint32_t format, uint32_t usage);
};
diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp
index 4cedcbf..24d5f9a 100644
--- a/services/surfaceflinger/Transform.cpp
+++ b/services/surfaceflinger/Transform.cpp
@@ -20,6 +20,7 @@
#include <utils/String8.h>
#include <ui/Region.h>
+#include "clz.h"
#include "Transform.h"
// ---------------------------------------------------------------------------
@@ -28,42 +29,6 @@ namespace android {
// ---------------------------------------------------------------------------
-template <typename T>
-static inline T min(T a, T b) {
- return a<b ? a : b;
-}
-template <typename T>
-static inline T min(T a, T b, T c) {
- return min(a, min(b, c));
-}
-template <typename T>
-static inline T min(T a, T b, T c, T d) {
- return min(a, b, min(c, d));
-}
-
-template <typename T>
-static inline T max(T a, T b) {
- return a>b ? a : b;
-}
-template <typename T>
-static inline T max(T a, T b, T c) {
- return max(a, max(b, c));
-}
-template <typename T>
-static inline T max(T a, T b, T c, T d) {
- return max(a, b, max(c, d));
-}
-
-template <typename T>
-static inline
-void swap(T& a, T& b) {
- T t(a);
- a = b;
- b = t;
-}
-
-// ---------------------------------------------------------------------------
-
Transform::Transform() {
reset();
}
diff --git a/services/surfaceflinger/clz.h b/services/surfaceflinger/clz.h
index ca44555..a4c5262 100644
--- a/services/surfaceflinger/clz.h
+++ b/services/surfaceflinger/clz.h
@@ -24,6 +24,41 @@ int inline clz(int32_t x) {
return __builtin_clz(x);
}
+template <typename T>
+static inline T min(T a, T b) {
+ return a<b ? a : b;
+}
+template <typename T>
+static inline T min(T a, T b, T c) {
+ return min(a, min(b, c));
+}
+template <typename T>
+static inline T min(T a, T b, T c, T d) {
+ return min(a, b, min(c, d));
+}
+
+template <typename T>
+static inline T max(T a, T b) {
+ return a>b ? a : b;
+}
+template <typename T>
+static inline T max(T a, T b, T c) {
+ return max(a, max(b, c));
+}
+template <typename T>
+static inline T max(T a, T b, T c, T d) {
+ return max(a, b, max(c, d));
+}
+
+template <typename T>
+static inline
+void swap(T& a, T& b) {
+ T t(a);
+ a = b;
+ b = t;
+}
+
+
}; // namespace android
#endif /* ANDROID_SURFACE_FLINGER_CLZ_H */
diff --git a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
index 0d9d27d..ac66b48 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CDMALTEPhone.java
@@ -141,6 +141,11 @@ public class CDMALTEPhone extends CDMAPhone {
}
@Override
+ public String getDeviceSvn() {
+ return mImeiSv;
+ }
+
+ @Override
protected void log(String s) {
if (DBG)
Log.d(LOG_TAG, "[CDMALTEPhone] " + s);
diff --git a/tests/TileBenchmark/Android.mk b/tests/TileBenchmark/Android.mk
new file mode 100644
index 0000000..430f0f1
--- /dev/null
+++ b/tests/TileBenchmark/Android.mk
@@ -0,0 +1,32 @@
+# Copyright (C) 2011 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_PACKAGE_NAME := TileBenchmark
+
+include $(BUILD_PACKAGE)
+
+##################################################
+include $(CLEAR_VARS)
+
+include $(BUILD_MULTI_PREBUILT)
+
+# Use the folloing include to make our test apk.
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/TileBenchmark/AndroidManifest.xml b/tests/TileBenchmark/AndroidManifest.xml
new file mode 100644
index 0000000..663cc0d
--- /dev/null
+++ b/tests/TileBenchmark/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ android:versionCode="1"
+ android:versionName="1.0" package="com.test.tilebenchmark">
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <application android:icon="@drawable/icon"
+ android:label="@string/app_name"
+ android:hardwareAccelerated="true">
+ <activity android:name=".ProfileActivity"
+ android:label="@string/profile_activity">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity android:name=".PlaybackActivity"
+ android:label="@string/playback_activity">
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/TileBenchmark/res/drawable-hdpi/icon.png b/tests/TileBenchmark/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/tests/TileBenchmark/res/drawable-hdpi/icon.png
Binary files differ
diff --git a/tests/TileBenchmark/res/drawable-ldpi/icon.png b/tests/TileBenchmark/res/drawable-ldpi/icon.png
new file mode 100644
index 0000000..1095584
--- /dev/null
+++ b/tests/TileBenchmark/res/drawable-ldpi/icon.png
Binary files differ
diff --git a/tests/TileBenchmark/res/drawable-mdpi/icon.png b/tests/TileBenchmark/res/drawable-mdpi/icon.png
new file mode 100644
index 0000000..a07c69f
--- /dev/null
+++ b/tests/TileBenchmark/res/drawable-mdpi/icon.png
Binary files differ
diff --git a/tests/TileBenchmark/res/layout/main.xml b/tests/TileBenchmark/res/layout/main.xml
new file mode 100644
index 0000000..4a81da6
--- /dev/null
+++ b/tests/TileBenchmark/res/layout/main.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <LinearLayout
+ android:id="@+id/top"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <Button
+ android:id="@+id/inspect"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/inspect_log"
+ />
+ <Spinner
+ android:id="@+id/velocity"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:prompt="@string/desired_scroll_velocity"
+ />
+ <EditText
+ android:id="@+id/url"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:inputType="textUri"
+ android:imeOptions="actionGo"
+ android:layout_weight="1"
+ />
+ </LinearLayout>
+ <com.test.tilebenchmark.ProfiledWebView
+ android:id="@+id/web"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
+</LinearLayout>
diff --git a/tests/TileBenchmark/res/layout/playback.xml b/tests/TileBenchmark/res/layout/playback.xml
new file mode 100644
index 0000000..aa1c8a4
--- /dev/null
+++ b/tests/TileBenchmark/res/layout/playback.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ >
+ <LinearLayout
+ android:id="@+id/top"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ >
+ <Button
+ android:id="@+id/backward"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/backward"
+ />
+ <TextView
+ android:id="@+id/frame_display"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:layout_weight="1"
+ />
+ <Button
+ android:id="@+id/forward"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/forward"
+ />
+ <SeekBar
+ android:id="@+id/seek_bar"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="10"
+ />
+ </LinearLayout>
+ <com.test.tilebenchmark.PlaybackView
+ android:id="@+id/playback"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ />
+</LinearLayout>
diff --git a/tests/TileBenchmark/res/values/colors.xml b/tests/TileBenchmark/res/values/colors.xml
new file mode 100644
index 0000000..3958083
--- /dev/null
+++ b/tests/TileBenchmark/res/values/colors.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <!-- The color of tiles with valid textures -->
+ <color name="ready_tile">#ff4ac230</color>
+ <!-- The color of tiles with stale / invalid textures -->
+ <color name="unready_tile">#ff744400</color>
+ <!-- Background color for logged URLs -->
+ <color name="finished_url">#ff004000</color>
+ <!-- Background color for URLs with logging in progress -->
+ <color name="unfinished_url">#ff400000</color>
+</resources>
diff --git a/tests/TileBenchmark/res/values/strings.xml b/tests/TileBenchmark/res/values/strings.xml
new file mode 100644
index 0000000..f70ee2c
--- /dev/null
+++ b/tests/TileBenchmark/res/values/strings.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2011 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<resources>
+ <!-- Button, steps back a single frame [CHAR LIMIT=15] -->
+ <string name="backward">Backward</string>
+ <!-- Button, steps forward a single frame [CHAR LIMIT=15] -->
+ <string name="forward">Forward</string>
+ <!-- The name of the application [CHAR LIMIT=20] -->
+ <string name="app_name">TileBenchmark</string>
+ <!-- name of the auto-scroller / tile logger activity [CHAR LIMIT=100] -->
+ <string name="profile_activity">Webview Profiler</string>
+ <!-- name of the tile log playback activity [CHAR LIMIT=100] -->
+ <string name="playback_activity">Webview Tile Playback</string>
+ <!-- Button, loads another tile log [CHAR LIMIT=30] -->
+ <string name="loadbutton">Load</string>
+ <!-- Button, opens the playback activity [CHAR LIMIT=20] -->
+ <string name="inspect_log">Inspect Log</string>
+ <!-- The speed of auto-scrolling [CHAR LIMIT=30] -->
+ <string name="desired_scroll_velocity">Choose Scroll Velocity</string>
+ <!-- Pixels moved per frame [CHAR LIMIT=10] -->
+ <string-array name="velocity_array">
+ <item>1</item>
+ <item>25</item>
+ <item>50</item>
+ <item>100</item>
+ <item>200</item>
+ <item>400</item>
+ </string-array>
+ <!-- 25th percentile - 25% of frames fall below this value [CHAR LIMIT=12]
+ -->
+ <string name="percentile_25">25%ile</string>
+ <!-- 50th percentile - 50% of frames fall below this value (aka median)
+ [CHAR LIMIT=12] -->
+ <string name="percentile_50">median</string>
+ <!-- 75th percentile - 75% of frames fall below this value [CHAR LIMIT=12]
+ -->
+ <string name="percentile_75">75%ile</string>
+ <!-- Frame rate [CHAR LIMIT=15] -->
+ <string name="frames_per_second">Frames/sec</string>
+ <!-- Portion of viewport covered by good tiles [CHAR LIMIT=15] -->
+ <string name="viewport_coverage">Coverage</string>
+ <!-- Format string for stat value overlay [CHAR LIMIT=15] -->
+ <string name="format_stat">%4.4f</string>
+ <!-- Format string for displaying aggregate stats+values (nr of valid tiles,
+ etc.) [CHAR LIMIT=20] -->
+ <string name="format_stat_name">%1$9s %2$3d</string>
+ <!-- Text hovering over canvas, number of tiles ready [CHAR LIMIT=15] -->
+ <string name="ready_tiles">Ready Tiles</string>
+ <!-- Text hovering over canvas, number tiles not ready [CHAR LIMIT=15] -->
+ <string name="unready_tiles">Unready Tiles</string>
+ <!-- Text hovering over canvas, number of tiles that haven't been
+ allocated to a place on the page [CHAR LIMIT=15] -->
+ <string name="unplaced_tiles">Unplaced Tiles</string>
+</resources>
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java
new file mode 100644
index 0000000..5130f5d
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackActivity.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.test.tilebenchmark;
+
+import android.app.Activity;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.view.GestureDetector.SimpleOnGestureListener;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+
+/**
+ * Interface for playing back WebView tile rendering status. Draws viewport and
+ * states of tiles and statistics for off-line analysis.
+ */
+public class PlaybackActivity extends Activity {
+ private static final float SCROLL_SCALER = 0.125f;
+
+ PlaybackView mPlaybackView;
+ SeekBar mSeekBar;
+ Button mForward;
+ Button mBackward;
+ TextView mFrameDisplay;
+
+ private int mFrame = -1;
+ private int mFrameMax;
+
+ private class TouchFrameChangeListener extends SimpleOnGestureListener {
+ float mDist = 0;
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2,
+ float distanceX, float distanceY) {
+ // aggregate scrolls so that small ones can add up
+ mDist += distanceY * SCROLL_SCALER;
+ int intComponent = (int) Math.floor(Math.abs(mDist));
+ if (intComponent >= 1) {
+ int scrollDist = (mDist > 0) ? intComponent : -intComponent;
+ setFrame(null, mFrame + scrollDist);
+ mDist -= scrollDist;
+ }
+ return super.onScroll(e1, e2, distanceX, distanceY);
+ }
+ };
+
+ private class SeekFrameChangeListener implements OnSeekBarChangeListener {
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress,
+ boolean fromUser) {
+ setFrame(seekBar, progress);
+ }
+ };
+
+ private class LoadFileTask extends AsyncTask<String, Void, TileData[][]> {
+ @Override
+ protected TileData[][] doInBackground(String... params) {
+ TileData[][] data = null;
+ try {
+ FileInputStream fis = openFileInput(params[0]);
+ ObjectInputStream in = new ObjectInputStream(fis);
+ data = (TileData[][]) in.readObject();
+ in.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ } catch (ClassNotFoundException ex) {
+ ex.printStackTrace();
+ }
+ return data;
+ }
+
+ @Override
+ protected void onPostExecute(TileData data[][]) {
+ if (data == null) {
+ data = genTestPattern();
+ }
+ mPlaybackView.setData(data);
+
+ mFrameMax = data.length - 1;
+ mSeekBar.setMax(mFrameMax);
+
+ setFrame(null, 0);
+ }
+ }
+
+ private void setFrame(View changer, int f) {
+ if (f < 0) {
+ f = 0;
+ } else if (f > mFrameMax) {
+ f = mFrameMax;
+ }
+
+ if (mFrame == f) {
+ return;
+ }
+
+ mFrame = f;
+ mForward.setEnabled(mFrame != mFrameMax);
+ mBackward.setEnabled(mFrame != 0);
+ if (changer != mSeekBar) {
+ mSeekBar.setProgress(mFrame);
+ }
+ mFrameDisplay.setText(Integer.toString(mFrame));
+ mPlaybackView.setFrame(mFrame);
+ };
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.playback);
+
+ mPlaybackView = (PlaybackView) findViewById(R.id.playback);
+ mSeekBar = (SeekBar) findViewById(R.id.seek_bar);
+ mForward = (Button) findViewById(R.id.forward);
+ mBackward = (Button) findViewById(R.id.backward);
+ mFrameDisplay = (TextView) findViewById(R.id.frame_display);
+
+ mForward.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setFrame(v, mFrame + 1);
+ }
+ });
+
+ mBackward.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ setFrame(v, mFrame - 1);
+ }
+ });
+
+ mSeekBar.setOnSeekBarChangeListener(new SeekFrameChangeListener());
+
+ mPlaybackView.setOnGestureListener(new TouchFrameChangeListener());
+
+ new LoadFileTask().execute(ProfileActivity.TEMP_FILENAME);
+ }
+
+ private TileData[][] genTestPattern() {
+ final int XMAX = 5;
+ final int FRAMEMAX = 99;
+
+ TileData example[][] = new TileData[FRAMEMAX][];
+ for (int frame = 0; frame < FRAMEMAX; frame++) {
+ int numTiles = frame + 10;
+
+ example[frame] = new TileData[numTiles];
+ for (int t = 0; t < numTiles; t++) {
+ int x = t % XMAX;
+ int y = t / XMAX;
+ boolean isReady = y * 10 < frame;
+ example[frame][t] = new TileData(x, y, isReady, 0);
+ }
+ }
+ return example;
+ }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
new file mode 100644
index 0000000..db4a341
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackGraphs.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.test.tilebenchmark;
+
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.ShapeDrawable;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class PlaybackGraphs {
+ private static final int BAR_WIDTH = PlaybackView.TILEX * 3;
+ private static final float CANVAS_SCALE = 0.2f;
+ private static final double IDEAL_FRAMES = 60;
+ private static final int LABELOFFSET = 100;
+ private static Paint whiteLabels;
+
+ private static double viewportCoverage(int l, int b, int r, int t,
+ int tileIndexX,
+ int tileIndexY) {
+ if (tileIndexX * PlaybackView.TILEX < r
+ && (tileIndexX + 1) * PlaybackView.TILEX >= l
+ && tileIndexY * PlaybackView.TILEY < t
+ && (tileIndexY + 1) * PlaybackView.TILEY >= b) {
+ return 1.0f;
+ }
+ return 0.0f;
+ }
+
+ private interface MetricGen {
+ public double getValue(TileData[] frame);
+
+ public double getMax();
+
+ public int getLabelId();
+ };
+
+ private static MetricGen[] Metrics = new MetricGen[] {
+ new MetricGen() {
+ // framerate graph
+ @Override
+ public double getValue(TileData[] frame) {
+ int renderTimeUS = frame[0].level;
+ return 1.0e6f / renderTimeUS;
+ }
+
+ @Override
+ public double getMax() {
+ return IDEAL_FRAMES;
+ }
+
+ @Override
+ public int getLabelId() {
+ return R.string.frames_per_second;
+ }
+ }, new MetricGen() {
+ // coverage graph
+ @Override
+ public double getValue(TileData[] frame) {
+ int l = frame[0].x, b = frame[0].y;
+ int r = frame[1].x, t = frame[1].y;
+ double total = 0, totalCount = 0;
+ for (int tileID = 2; tileID < frame.length; tileID++) {
+ TileData data = frame[tileID];
+ double coverage = viewportCoverage(l, b, r, t, data.x,
+ data.y);
+ total += coverage * (data.isReady ? 1 : 0);
+ totalCount += coverage;
+ }
+ if (totalCount == 0) {
+ return -1;
+ }
+ return total / totalCount;
+ }
+
+ @Override
+ public double getMax() {
+ return 1;
+ }
+
+ @Override
+ public int getLabelId() {
+ return R.string.viewport_coverage;
+ }
+ }
+ };
+
+ private interface StatGen {
+ public double getValue(double sortedValues[]);
+
+ public int getLabelId();
+ }
+
+ public static double getPercentile(double sortedValues[], double ratioAbove) {
+ double index = ratioAbove * (sortedValues.length - 1);
+ int intIndex = (int) Math.floor(index);
+ if (index == intIndex) {
+ return sortedValues[intIndex];
+ }
+ double alpha = index - intIndex;
+ return sortedValues[intIndex] * (1 - alpha)
+ + sortedValues[intIndex + 1] * (alpha);
+ }
+
+ private static StatGen[] Stats = new StatGen[] {
+ new StatGen() {
+ @Override
+ public double getValue(double[] sortedValues) {
+ return getPercentile(sortedValues, 0.25);
+ }
+
+ @Override
+ public int getLabelId() {
+ return R.string.percentile_25;
+ }
+ }, new StatGen() {
+ @Override
+ public double getValue(double[] sortedValues) {
+ return getPercentile(sortedValues, 0.5);
+ }
+
+ @Override
+ public int getLabelId() {
+ return R.string.percentile_50;
+ }
+ }, new StatGen() {
+ @Override
+ public double getValue(double[] sortedValues) {
+ return getPercentile(sortedValues, 0.75);
+ }
+
+ @Override
+ public int getLabelId() {
+ return R.string.percentile_75;
+ }
+ },
+ };
+
+ public PlaybackGraphs() {
+ whiteLabels = new Paint();
+ whiteLabels.setColor(Color.WHITE);
+ whiteLabels.setTextSize(PlaybackView.TILEY / 3);
+ }
+
+ private ArrayList<ShapeDrawable> mShapes = new ArrayList<ShapeDrawable>();
+ private double[][] mStats = new double[Metrics.length][Stats.length];
+
+ public void setData(TileData[][] tileProfilingData) {
+ mShapes.clear();
+ double metricValues[] = new double[tileProfilingData.length];
+
+ if (tileProfilingData.length == 0) {
+ return;
+ }
+
+ for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
+ // create graph out of rectangles, one per frame
+ int lastBar = 0;
+ for (int frameIndex = 0; frameIndex < tileProfilingData.length; frameIndex++) {
+ TileData frame[] = tileProfilingData[frameIndex];
+ int newBar = (frame[0].y + frame[1].y) / 2;
+
+ MetricGen s = Metrics[metricIndex];
+ double absoluteValue = s.getValue(frame);
+ double relativeValue = absoluteValue / s.getMax();
+ int rightPos = (int) (-BAR_WIDTH * metricIndex);
+ int leftPos = (int) (-BAR_WIDTH * (metricIndex + relativeValue));
+
+ ShapeDrawable graphBar = new ShapeDrawable();
+ graphBar.getPaint().setColor(Color.BLUE);
+ graphBar.setBounds(leftPos, lastBar, rightPos, newBar);
+
+ mShapes.add(graphBar);
+ metricValues[frameIndex] = absoluteValue;
+ lastBar = newBar;
+ }
+
+ // store aggregate statistics per metric (median, and similar)
+ Arrays.sort(metricValues);
+ for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
+ mStats[metricIndex][statIndex] = Stats[statIndex]
+ .getValue(metricValues);
+ }
+ }
+ }
+
+ public void drawVerticalShiftedShapes(Canvas canvas,
+ ArrayList<ShapeDrawable> shapes) {
+ // Shapes drawn here are drawn relative to the viewRect
+ Rect viewRect = shapes.get(shapes.size() - 1).getBounds();
+ canvas.translate(0, 5 * PlaybackView.TILEY - viewRect.top);
+
+ for (ShapeDrawable shape : mShapes) {
+ shape.draw(canvas);
+ }
+ for (ShapeDrawable shape : shapes) {
+ shape.draw(canvas);
+ }
+ }
+
+ public void draw(Canvas canvas, ArrayList<ShapeDrawable> shapes,
+ String[] strings, Resources resources) {
+ canvas.scale(CANVAS_SCALE, CANVAS_SCALE);
+
+ canvas.translate(BAR_WIDTH * Metrics.length, 0);
+
+ canvas.save();
+ drawVerticalShiftedShapes(canvas, shapes);
+ canvas.restore();
+
+ for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
+ String label = resources.getString(
+ Metrics[metricIndex].getLabelId());
+ int xPos = (metricIndex + 1) * -BAR_WIDTH;
+ int yPos = LABELOFFSET;
+ canvas.drawText(label, xPos, yPos, whiteLabels);
+ for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
+ label = resources.getString(R.string.format_stat, mStats[metricIndex][statIndex]);
+ yPos = LABELOFFSET + (1 + statIndex) * PlaybackView.TILEY / 2;
+ canvas.drawText(label, xPos, yPos, whiteLabels);
+ }
+ }
+ for (int stringIndex = 0; stringIndex < strings.length; stringIndex++) {
+ int yPos = LABELOFFSET + stringIndex * PlaybackView.TILEY / 2;
+ canvas.drawText(strings[stringIndex], 0, yPos, whiteLabels);
+ }
+ }
+
+ public Bundle getStatBundle(Resources resources) {
+ Bundle b = new Bundle();
+
+ for (int metricIndex = 0; metricIndex < Metrics.length; metricIndex++) {
+ for (int statIndex = 0; statIndex < Stats.length; statIndex++) {
+ String metricLabel = resources.getString(
+ Metrics[metricIndex].getLabelId());
+ String statLabel = resources.getString(
+ Stats[statIndex].getLabelId());
+ double value = mStats[metricIndex][statIndex];
+ b.putDouble(metricLabel + " " + statLabel, value);
+ }
+ }
+
+ return b;
+ }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
new file mode 100644
index 0000000..f104eac
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/PlaybackView.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.test.tilebenchmark;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.drawable.ShapeDrawable;
+import android.util.AttributeSet;
+import android.view.GestureDetector;
+import android.view.GestureDetector.OnGestureListener;
+import android.view.MotionEvent;
+import android.view.View;
+
+import java.util.ArrayList;
+
+public class PlaybackView extends View {
+ public static final int TILEX = 300;
+ public static final int TILEY = 300;
+
+ private Paint levelPaint = null, coordPaint = null, goldPaint = null;
+ private PlaybackGraphs mGraphs;
+
+ private ArrayList<ShapeDrawable> mTempShapes = new ArrayList<ShapeDrawable>();
+ private TileData mProfData[][] = null;
+ private GestureDetector mGestureDetector = null;
+ private String mRenderStrings[] = new String[3];
+
+ private class TileDrawable extends ShapeDrawable {
+ TileData tile;
+
+ public TileDrawable(TileData t) {
+ int tileColorId = t.isReady ? R.color.ready_tile
+ : R.color.unready_tile;
+ getPaint().setColor(getResources().getColor(tileColorId));
+
+ setBounds(t.x * TILEX, t.y * TILEY, (t.x + 1) * TILEX, (t.y + 1)
+ * TILEY);
+ this.tile = t;
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ canvas.drawText(Integer.toString(tile.level), getBounds().left,
+ getBounds().bottom, levelPaint);
+ canvas.drawText(tile.x + "," + tile.y, getBounds().left,
+ ((getBounds().bottom + getBounds().top) / 2), coordPaint);
+ }
+ }
+
+ public PlaybackView(Context context) {
+ super(context);
+ init();
+ }
+
+ public PlaybackView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public PlaybackView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ public void setOnGestureListener(OnGestureListener gl) {
+ mGestureDetector = new GestureDetector(getContext(), gl);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ mGestureDetector.onTouchEvent(event);
+ return true;
+ }
+
+ private void init() {
+ levelPaint = new Paint();
+ levelPaint.setColor(Color.WHITE);
+ levelPaint.setTextSize(TILEY / 2);
+ coordPaint = new Paint();
+ coordPaint.setColor(Color.BLACK);
+ coordPaint.setTextSize(TILEY / 3);
+ goldPaint = new Paint();
+ goldPaint.setColor(0xffa0e010);
+ mGraphs = new PlaybackGraphs();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (mTempShapes == null || mTempShapes.isEmpty()) {
+ return;
+ }
+
+ mGraphs.draw(canvas, mTempShapes, mRenderStrings, getResources());
+ }
+
+ public int setFrame(int frame) {
+ if (mProfData == null || mProfData.length == 0) {
+ return 0;
+ }
+
+ int readyTiles = 0, unreadyTiles = 0, unplacedTiles = 0;
+ mTempShapes.clear();
+
+ // draw actual tiles
+ for (int tileID = 2; tileID < mProfData[frame].length; tileID++) {
+ TileData t = mProfData[frame][tileID];
+ mTempShapes.add(new TileDrawable(t));
+ if (t.isReady) {
+ readyTiles++;
+ } else {
+ unreadyTiles++;
+ }
+ if (t.x < 0 || t.y < 0) {
+ unplacedTiles++;
+ }
+ }
+ mRenderStrings[0] = getResources().getString(R.string.format_stat_name,
+ getResources().getString(R.string.ready_tiles), readyTiles);
+ mRenderStrings[1] = getResources().getString(R.string.format_stat_name,
+ getResources().getString(R.string.unready_tiles), unreadyTiles);
+ mRenderStrings[2] = getResources().getString(R.string.format_stat_name,
+ getResources().getString(R.string.unplaced_tiles), unplacedTiles);
+
+ // draw view rect (using first two TileData objects)
+ ShapeDrawable viewShape = new ShapeDrawable();
+ viewShape.getPaint().setColor(0xff0000ff);
+ viewShape.setAlpha(64);
+ viewShape.setBounds(mProfData[frame][0].x, mProfData[frame][0].y,
+ mProfData[frame][1].x, mProfData[frame][1].y);
+ mTempShapes.add(viewShape);
+ this.invalidate();
+ return frame;
+ }
+
+ public void setData(TileData[][] tileProfilingData) {
+ mProfData = tileProfilingData;
+
+ mGraphs.setData(mProfData);
+ }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
new file mode 100644
index 0000000..23b6275
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfileActivity.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.test.tilebenchmark;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.os.CountDownTimer;
+import android.util.Pair;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Spinner;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+
+/**
+ * Interface for profiling the webview's scrolling, with simple controls on how
+ * to scroll, and what content to load.
+ */
+public class ProfileActivity extends Activity {
+
+ public interface ProfileCallback {
+ public void profileCallback(TileData data[][]);
+ }
+
+ public static final String TEMP_FILENAME = "profile.tiles";
+ private static final int LOAD_TEST_DELAY = 2000; // nr of millis after load,
+ // before test
+
+ Button mInspectButton;
+ Spinner mVelocitySpinner;
+ EditText mUrl;
+ ProfiledWebView mWeb;
+ ProfileCallback mCallback;
+
+ private class VelocitySelectedListener implements OnItemSelectedListener {
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view,
+ int position, long id) {
+ String speedStr = parent.getItemAtPosition(position).toString();
+ int speedInt = Integer.parseInt(speedStr);
+ mWeb.setAutoScrollSpeed(speedInt);
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ }
+ }
+
+ private class LoggingWebViewClient extends WebViewClient {
+ @Override
+ public boolean shouldOverrideUrlLoading(WebView view, String url) {
+ return false;
+ }
+
+ @Override
+ public void onPageStarted(WebView view, String url, Bitmap favicon) {
+ super.onPageStarted(view, url, favicon);
+ mUrl.setText(url);
+ }
+
+ @Override
+ public void onPageFinished(WebView view, String url) {
+ super.onPageFinished(view, url);
+ view.requestFocus();
+ new CountDownTimer(LOAD_TEST_DELAY, LOAD_TEST_DELAY) {
+ @Override
+ public void onTick(long millisUntilFinished) {
+ }
+
+ @Override
+ public void onFinish() {
+ mWeb.startScrollTest(mCallback);
+ }
+ }.start();
+ }
+ }
+
+ private class StoreFileTask extends
+ AsyncTask<Pair<String, TileData[][]>, Void, Void> {
+
+ @Override
+ protected Void doInBackground(Pair<String, TileData[][]>... params) {
+ try {
+ FileOutputStream fos = openFileOutput(params[0].first,
+ Context.MODE_PRIVATE);
+ ObjectOutputStream out = new ObjectOutputStream(fos);
+ out.writeObject(params[0].second);
+ out.close();
+ } catch (IOException ex) {
+ ex.printStackTrace();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void v) {
+ mUrl.setBackgroundResource(R.color.finished_url);
+ }
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ mInspectButton = (Button) findViewById(R.id.inspect);
+ mVelocitySpinner = (Spinner) findViewById(R.id.velocity);
+ mUrl = (EditText) findViewById(R.id.url);
+ mWeb = (ProfiledWebView) findViewById(R.id.web);
+ mCallback = new ProfileCallback() {
+ @SuppressWarnings("unchecked")
+ @Override
+ public void profileCallback(TileData[][] data) {
+ new StoreFileTask().execute(new Pair<String, TileData[][]>(TEMP_FILENAME, data));
+ }
+ };
+
+ // Inspect button (opens PlaybackActivity)
+ mInspectButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ startActivity(new Intent(ProfileActivity.this,
+ PlaybackActivity.class));
+ }
+ });
+
+ // Velocity spinner
+ ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
+ this, R.array.velocity_array,
+ android.R.layout.simple_spinner_item);
+ adapter.setDropDownViewResource(
+ android.R.layout.simple_spinner_dropdown_item);
+ mVelocitySpinner.setAdapter(adapter);
+ mVelocitySpinner.setOnItemSelectedListener(
+ new VelocitySelectedListener());
+ mVelocitySpinner.setSelection(3);
+
+ // Custom profiling WebView
+ WebSettings settings = mWeb.getSettings();
+ settings.setJavaScriptEnabled(true);
+ settings.setSupportZoom(true);
+ settings.setEnableSmoothTransition(true);
+ settings.setBuiltInZoomControls(true);
+ settings.setLoadWithOverviewMode(true);
+ mWeb.setWebViewClient(new LoggingWebViewClient());
+
+ // URL text entry
+ mUrl.setOnEditorActionListener(new OnEditorActionListener() {
+ public boolean onEditorAction(TextView v, int actionId,
+ KeyEvent event) {
+ String url = mUrl.getText().toString();
+ mUrl.setBackgroundResource(R.color.unfinished_url);
+ mWeb.loadUrl(url);
+ mWeb.requestFocus();
+ return true;
+ }
+ });
+ }
+
+ public void setCallback(ProfileCallback callback) {
+ mCallback = callback;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if ((keyCode == KeyEvent.KEYCODE_BACK) && mWeb.canGoBack()) {
+ mWeb.goBack();
+ return true;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
new file mode 100644
index 0000000..6560624
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/ProfiledWebView.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.test.tilebenchmark;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.webkit.WebView;
+
+import com.test.tilebenchmark.ProfileActivity.ProfileCallback;
+
+public class ProfiledWebView extends WebView {
+ private int mSpeed;
+
+ private boolean isScrolling = false;
+ private ProfileCallback mCallback;
+
+ public ProfiledWebView(Context context) {
+ super(context);
+ }
+
+ public ProfiledWebView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ProfiledWebView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public ProfiledWebView(Context context, AttributeSet attrs, int defStyle,
+ boolean privateBrowsing) {
+ super(context, attrs, defStyle, privateBrowsing);
+ }
+
+ @Override
+ protected void onDraw(android.graphics.Canvas canvas) {
+ if (isScrolling) {
+ if (canScrollVertically(1)) {
+ scrollBy(0, mSpeed);
+ } else {
+ stopScrollTest();
+ isScrolling = false;
+ }
+ }
+ super.onDraw(canvas);
+ }
+
+ /*
+ * Called once the page is loaded to start scrolling for evaluating tiles
+ */
+ public void startScrollTest(ProfileCallback callback) {
+ isScrolling = true;
+ mCallback = callback;
+ super.tileProfilingStart();
+ invalidate();
+ }
+
+ /*
+ * Called once the page has stopped scrolling
+ */
+ public void stopScrollTest() {
+ float testRatio = super.tileProfilingStop();
+
+ TileData data[][] = new TileData[super.tileProfilingNumFrames()][];
+ for (int frame = 0; frame < data.length; frame++) {
+ data[frame] = new TileData[
+ super.tileProfilingNumTilesInFrame(frame)];
+ for (int tile = 0; tile < data[frame].length; tile++) {
+ int x = super.tileProfilingGetX(frame, tile);
+ int y = super.tileProfilingGetY(frame, tile);
+ boolean isReady = super.tileProfilingGetReady(frame, tile);
+ int level = super.tileProfilingGetLevel(frame, tile);
+
+ data[frame][tile] = new TileData(x, y, isReady, level);
+ }
+ }
+ super.tileProfilingClear();
+
+ mCallback.profileCallback(data);
+ }
+
+ @Override
+ public void loadUrl(String url) {
+ if (!url.startsWith("http://")) {
+ url = "http://" + url;
+ }
+ super.loadUrl(url);
+ }
+
+ public void setAutoScrollSpeed(int speedInt) {
+ mSpeed = speedInt;
+ }
+}
diff --git a/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
new file mode 100644
index 0000000..7d4bb9f
--- /dev/null
+++ b/tests/TileBenchmark/src/com/test/tilebenchmark/TileData.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.test.tilebenchmark;
+
+import java.io.Serializable;
+
+public class TileData implements Serializable {
+ public int x, y;
+ public boolean isReady;
+ public int level;
+
+ public TileData(int x, int y, boolean isReady, int level) {
+ this.x = x;
+ this.y = y;
+ this.isReady = isReady;
+ this.level = level;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index b4448a9..8e3ed93 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -1093,33 +1093,6 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_drawTextWithGlyphs(int nativeCanvas, char[] text,
- int index, int count, float x,
- float y, int flags, int paint) {
- native_drawText(nativeCanvas, text, index, count, x, y, flags, paint);
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_drawTextWithGlyphs(int nativeCanvas, String text,
- int start, int end, float x,
- float y, int flags, int paint) {
- int count = end - start;
- char[] buffer = TemporaryBuffer.obtain(count);
- TextUtils.getChars(text, start, end, buffer, 0);
-
- native_drawText(nativeCanvas, text, 0, count, x, y, flags, paint);
- }
-
- @LayoutlibDelegate
- /*package*/ static void native_drawGlyphs(int nativeCanvas, char[] glyphs,
- int index, int count, float x,
- float y, int flags, int paint) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawGlyphs is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
/*package*/ static void native_drawPosText(int nativeCanvas,
char[] text, int index,
int count, float[] pos,
diff --git a/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
new file mode 100644
index 0000000..52b8f34
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/text/AndroidBidi_Delegate.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+
+/**
+ * Delegate used to provide new implementation for the native methods of {@link AndroidBidi}
+ *
+ * Through the layoutlib_create tool, the original methods of AndroidBidi have been replaced
+ * by calls to methods of the same name in this delegate class.
+ *
+ */
+public class AndroidBidi_Delegate {
+
+ @LayoutlibDelegate
+ /*package*/ static int runBidi(int dir, char[] chs, byte[] chInfo, int n, boolean haveInfo) {
+ // return the equivalent of Layout.DIR_LEFT_TO_RIGHT
+ // TODO: actually figure the direction.
+ return 0;
+ }
+}
diff --git a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
index ec7a67e..f056040 100644
--- a/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/view/inputmethod/InputMethodManager_Delegate.java
@@ -19,6 +19,7 @@ package android.view.inputmethod;
import com.android.layoutlib.bridge.android.BridgeIInputMethodManager;
import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+import android.content.Context;
import android.os.Looper;
@@ -44,6 +45,18 @@ public class InputMethodManager_Delegate {
mainLooper);
}
return InputMethodManager.mInstance;
+ }
+
+ @LayoutlibDelegate
+ /*package*/ static InputMethodManager getInstance(Context context) {
+ synchronized (InputMethodManager.mInstanceSync) {
+ if (InputMethodManager.mInstance != null) {
+ return InputMethodManager.mInstance;
+ }
+ InputMethodManager.mInstance = new InputMethodManager(new BridgeIInputMethodManager(),
+ Looper.myLooper());
+ }
+ return InputMethodManager.mInstance;
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
index 2519ebc..23e0ca1 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeIInputMethodManager.java
@@ -188,4 +188,10 @@ public class BridgeIInputMethodManager implements IInputMethodManager {
return null;
}
+ public boolean setAdditionalInputMethodSubtypes(IBinder arg0, InputMethodSubtype[] arg1)
+ throws RemoteException {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
}
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index df7e04f..93a35cc 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -155,6 +155,7 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.Typeface",
"android.graphics.Xfermode",
"android.os.SystemClock",
+ "android.text.AndroidBidi",
"android.util.FloatMath",
"android.view.Display",
"libcore.icu.ICU",
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index e3661bf..7bb927b 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -81,6 +81,24 @@ public class WifiInfo implements Parcelable {
mHiddenSSID = false;
}
+ /**
+ * Copy constructor
+ * @hide
+ */
+ public WifiInfo(WifiInfo source) {
+ if (source != null) {
+ mSupplicantState = source.mSupplicantState;
+ mBSSID = source.mBSSID;
+ mSSID = source.mSSID;
+ mNetworkId = source.mNetworkId;
+ mHiddenSSID = source.mHiddenSSID;
+ mRssi = source.mRssi;
+ mLinkSpeed = source.mLinkSpeed;
+ mIpAddress = source.mIpAddress;
+ mMacAddress = source.mMacAddress;
+ }
+ }
+
void setSSID(String SSID) {
mSSID = SSID;
// network is considered not hidden by default
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 9d1bdd4..cd6621f 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -230,11 +230,13 @@ public class WifiManager {
/**
* Broadcast intent action indicating that the state of Wi-Fi connectivity
* has changed. One extra provides the new state
- * in the form of a {@link android.net.NetworkInfo} object. If the new state is
- * CONNECTED, a second extra may provide the BSSID of the access point,
+ * in the form of a {@link android.net.NetworkInfo} object. If the new
+ * state is CONNECTED, additional extras may provide the BSSID and WifiInfo of
+ * the access point.
* as a {@code String}.
* @see #EXTRA_NETWORK_INFO
* @see #EXTRA_BSSID
+ * @see #EXTRA_WIFI_INFO
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
@@ -252,6 +254,13 @@ public class WifiManager {
*/
public static final String EXTRA_BSSID = "bssid";
/**
+ * The lookup key for a {@link android.net.wifi.WifiInfo} object giving the
+ * information about the access point to which we are connected. Only present
+ * when the new state is CONNECTED. Retrieve with
+ * {@link android.content.Intent#getParcelableExtra(String)}.
+ */
+ public static final String EXTRA_WIFI_INFO = "wifiInfo";
+ /**
* Broadcast intent action indicating that the state of establishing a connection to
* an access point has changed.One extra provides the new
* {@link SupplicantState}. Note that the supplicant state is Wi-Fi specific, and
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 8c28319..12efeb1 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -1374,6 +1374,8 @@ public class WifiStateMachine extends StateMachine {
intent.putExtra(WifiManager.EXTRA_LINK_PROPERTIES, new LinkProperties (mLinkProperties));
if (bssid != null)
intent.putExtra(WifiManager.EXTRA_BSSID, bssid);
+ if (mNetworkInfo.getState() == NetworkInfo.State.CONNECTED)
+ intent.putExtra(WifiManager.EXTRA_WIFI_INFO, new WifiInfo(mWifiInfo));
mContext.sendStickyBroadcast(intent);
}