diff options
185 files changed, 7749 insertions, 4360 deletions
diff --git a/Android.mk b/Android.mk index 08ee65effab1..52ebd6fbc334 100644 --- a/Android.mk +++ b/Android.mk @@ -188,6 +188,7 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \ telephony/java/com/android/internal/telephony/IIccPhoneBook.aidl \ telephony/java/com/android/internal/telephony/ISms.aidl \ + telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \ telephony/java/com/android/internal/telephony/IExtendedNetworkService.aidl \ vpn/java/android/net/vpn/IVpnService.aidl \ @@ -416,8 +417,8 @@ web_docs_sample_code_flags := \ resources/samples/NotePad "Note Pad" \ -samplecode $(sample_dir)/SampleSyncAdapter \ resources/samples/SampleSyncAdapter "Sample Sync Adapter" \ - -samplecode frameworks/base/libs/rs/java \ - resources/samples/Renderscript "Renderscript" \ + -samplecode $(sample_dir)/RenderScript \ + resources/samples/RenderScript "RenderScript" \ -samplecode $(sample_dir)/SearchableDictionary \ resources/samples/SearchableDictionary "Searchable Dictionary v2" \ -samplecode $(sample_dir)/SipDemo \ diff --git a/api/current.xml b/api/current.xml index 90b46ff7cec4..83055bf50121 100644 --- a/api/current.xml +++ b/api/current.xml @@ -111,17 +111,6 @@ visibility="public" > </field> -<field name="ACCESS_USB" - type="java.lang.String" - transient="false" - volatile="false" - value=""android.permission.ACCESS_USB"" - static="true" - final="true" - deprecated="not deprecated" - visibility="public" -> -</field> <field name="ACCESS_WIFI_STATE" type="java.lang.String" transient="false" @@ -39947,7 +39936,7 @@ visibility="public" > </field> -<field name="resizableMode" +<field name="resizeMode" type="int" transient="false" volatile="false" @@ -61267,6 +61256,28 @@ visibility="public" > </field> +<field name="FEATURE_USB_ACCESSORY" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.hardware.usb.accessory"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> +<field name="FEATURE_USB_HOST" + type="java.lang.String" + transient="false" + volatile="false" + value=""android.hardware.usb.host"" + static="true" + final="true" + deprecated="not deprecated" + visibility="public" +> +</field> <field name="FEATURE_WIFI" type="java.lang.String" transient="false" @@ -198789,6 +198800,23 @@ <parameter name="buffer" type="android.text.Spannable"> </parameter> </method> +<method name="onGenericMotionEvent" + return="boolean" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="widget" type="android.widget.TextView"> +</parameter> +<parameter name="text" type="android.text.Spannable"> +</parameter> +<parameter name="event" type="android.view.MotionEvent"> +</parameter> +</method> <method name="onKeyDown" return="boolean" abstract="false" @@ -199862,6 +199890,23 @@ <parameter name="text" type="android.text.Spannable"> </parameter> </method> +<method name="onGenericMotionEvent" + return="boolean" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="widget" type="android.widget.TextView"> +</parameter> +<parameter name="text" type="android.text.Spannable"> +</parameter> +<parameter name="event" type="android.view.MotionEvent"> +</parameter> +</method> <method name="onKeyDown" return="boolean" abstract="true" @@ -266599,7 +266644,7 @@ deprecated="not deprecated" visibility="public" > -<parameter name="t" type="T"> +<parameter name="arg0" type="T"> </parameter> </method> </interface> diff --git a/cmds/stagefright/Android.mk b/cmds/stagefright/Android.mk index 178032d59add..1b13dd954535 100644 --- a/cmds/stagefright/Android.mk +++ b/cmds/stagefright/Android.mk @@ -8,7 +8,7 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libstagefright libmedia libutils libbinder libstagefright_foundation \ - libskia + libskia libsurfaceflinger_client libgui LOCAL_C_INCLUDES:= \ $(JNI_H_INCLUDE) \ diff --git a/cmds/stagefright/stagefright.cpp b/cmds/stagefright/stagefright.cpp index a43b190a3757..a875c3afeeb7 100644 --- a/cmds/stagefright/stagefright.cpp +++ b/cmds/stagefright/stagefright.cpp @@ -55,6 +55,11 @@ #include <fcntl.h> +#include <gui/SurfaceTextureClient.h> + +#include <surfaceflinger/ISurfaceComposer.h> +#include <surfaceflinger/SurfaceComposerClient.h> + using namespace android; static long gNumRepetitions; @@ -66,6 +71,10 @@ static bool gWriteMP4; static bool gDisplayHistogram; static String8 gWriteMP4Filename; +static sp<ANativeWindow> gSurface; + +#define USE_SURFACE_COMPOSER 0 + static int64_t getNowUs() { struct timeval tv; gettimeofday(&tv, NULL); @@ -138,7 +147,8 @@ static void playSource(OMXClient *client, sp<MediaSource> &source) { rawSource = OMXCodec::Create( client->interface(), meta, false /* createEncoder */, source, NULL /* matchComponentName */, - gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0); + gPreferSoftwareCodec ? OMXCodec::kPreferSoftwareCodecs : 0, + gSurface); if (rawSource == NULL) { fprintf(stderr, "Failed to instantiate decoder for '%s'.\n", mime); @@ -540,6 +550,7 @@ static void usage(const char *me) { fprintf(stderr, " -k seek test\n"); fprintf(stderr, " -x display a histogram of decoding times/fps " "(video only)\n"); + fprintf(stderr, " -S allocate buffers from a surface\n"); } int main(int argc, char **argv) { @@ -550,6 +561,7 @@ int main(int argc, char **argv) { bool dumpProfiles = false; bool extractThumbnail = false; bool seekTest = false; + bool useSurfaceAlloc = false; gNumRepetitions = 1; gMaxNumFrames = 0; gReproduceBug = -1; @@ -563,7 +575,7 @@ int main(int argc, char **argv) { sp<LiveSession> liveSession; int res; - while ((res = getopt(argc, argv, "han:lm:b:ptsow:kx")) >= 0) { + while ((res = getopt(argc, argv, "han:lm:b:ptsow:kxS")) >= 0) { switch (res) { case 'a': { @@ -642,6 +654,12 @@ int main(int argc, char **argv) { break; } + case 'S': + { + useSurfaceAlloc = true; + break; + } + case '?': case 'h': default: @@ -780,6 +798,39 @@ int main(int argc, char **argv) { } } + sp<SurfaceComposerClient> composerClient; + sp<SurfaceControl> control; + + if (useSurfaceAlloc && !audioOnly) { +#if USE_SURFACE_COMPOSER + composerClient = new SurfaceComposerClient; + CHECK_EQ(composerClient->initCheck(), (status_t)OK); + + control = composerClient->createSurface( + getpid(), + String8("A Surface"), + 0, + 1280, + 800, + PIXEL_FORMAT_RGB_565, + 0); + + CHECK(control != NULL); + CHECK(control->isValid()); + + CHECK_EQ(composerClient->openTransaction(), (status_t)OK); + CHECK_EQ(control->setLayer(30000), (status_t)OK); + CHECK_EQ(control->show(), (status_t)OK); + CHECK_EQ(composerClient->closeTransaction(), (status_t)OK); + + gSurface = control->getSurface(); + CHECK(gSurface != NULL); +#else + sp<SurfaceTexture> texture = new SurfaceTexture(0 /* tex */); + gSurface = new SurfaceTextureClient(texture); +#endif + } + DataSource::RegisterDefaultSniffers(); OMXClient client; @@ -957,6 +1008,14 @@ int main(int argc, char **argv) { } } + if (useSurfaceAlloc && !audioOnly) { + gSurface.clear(); + +#if USE_SURFACE_COMPOSER + composerClient->dispose(); +#endif + } + client.disconnect(); return 0; diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java index 2e70a569c095..c91cdca7c2e1 100644 --- a/core/java/android/accounts/AccountManagerService.java +++ b/core/java/android/accounts/AccountManagerService.java @@ -101,7 +101,6 @@ public class AccountManagerService private final IAccountAuthenticatorCache mAuthenticatorCache; private final DatabaseHelper mOpenHelper; - private final SimWatcher mSimWatcher; private static final String TABLE_ACCOUNTS = "accounts"; private static final String ACCOUNTS_ID = "_id"; @@ -208,7 +207,6 @@ public class AccountManagerService mAuthenticatorCache = authenticatorCache; mAuthenticatorCache.setListener(this, null /* Handler */); - mSimWatcher = new SimWatcher(mContext); sThis.set(this); validateAccountsAndPopulateCache(); @@ -1739,100 +1737,6 @@ public class AccountManagerService } } - private class SimWatcher extends BroadcastReceiver { - public SimWatcher(Context context) { - // Re-scan the SIM card when the SIM state changes, and also if - // the disk recovers from a full state (we may have failed to handle - // things properly while the disk was full). - final IntentFilter filter = new IntentFilter(); - filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); - filter.addAction(Intent.ACTION_DEVICE_STORAGE_OK); - context.registerReceiver(this, filter); - } - - /** - * Compare the IMSI to the one stored in the login service's - * database. If they differ, erase all passwords and - * authtokens (and store the new IMSI). - */ - @Override - public void onReceive(Context context, Intent intent) { - // Check IMSI on every update; nothing happens if the IMSI - // is missing or unchanged. - TelephonyManager telephonyManager = - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - if (telephonyManager == null) { - Log.w(TAG, "failed to get TelephonyManager"); - return; - } - String imsi = telephonyManager.getSubscriberId(); - - // If the subscriber ID is an empty string, don't do anything. - if (TextUtils.isEmpty(imsi)) return; - - // If the current IMSI matches what's stored, don't do anything. - String storedImsi = getMetaValue("imsi"); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "current IMSI=" + imsi + "; stored IMSI=" + storedImsi); - } - if (imsi.equals(storedImsi)) return; - - // If a CDMA phone is unprovisioned, getSubscriberId() - // will return a different value, but we *don't* erase the - // passwords. We only erase them if it has a different - // subscriber ID once it's provisioned. - if (telephonyManager.getCurrentPhoneType() == TelephonyManager.PHONE_TYPE_CDMA) { - IBinder service = ServiceManager.checkService(Context.TELEPHONY_SERVICE); - if (service == null) { - Log.w(TAG, "call to checkService(TELEPHONY_SERVICE) failed"); - return; - } - ITelephony telephony = ITelephony.Stub.asInterface(service); - if (telephony == null) { - Log.w(TAG, "failed to get ITelephony interface"); - return; - } - boolean needsProvisioning; - try { - needsProvisioning = telephony.needsOtaServiceProvisioning(); - } catch (RemoteException e) { - Log.w(TAG, "exception while checking provisioning", e); - // default to NOT wiping out the passwords - needsProvisioning = true; - } - if (needsProvisioning) { - // if the phone needs re-provisioning, don't do anything. - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "current IMSI=" + imsi + " (needs provisioning); stored IMSI=" + - storedImsi); - } - return; - } - } - - if (!imsi.equals(storedImsi) && !TextUtils.isEmpty(storedImsi)) { - Log.w(TAG, "wiping all passwords and authtokens because IMSI changed (" - + "stored=" + storedImsi + ", current=" + imsi + ")"); - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - db.execSQL("DELETE from " + TABLE_AUTHTOKENS); - db.execSQL("UPDATE " + TABLE_ACCOUNTS + " SET " + ACCOUNTS_PASSWORD + " = ''"); - - synchronized (mCacheLock) { - mAuthTokenCache = new HashMap<Account, HashMap<String, String>>(); - } - - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - sendAccountsChangedBroadcast(); - } - setMetaValue("imsi", imsi); - } - } - public IBinder onBind(Intent intent) { return asBinder(); } diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java index 178567fdd881..d04fa57f84c2 100644 --- a/core/java/android/app/DownloadManager.java +++ b/core/java/android/app/DownloadManager.java @@ -907,8 +907,8 @@ public class DownloadManager { /** * Cancel downloads and remove them from the download manager. Each download will be stopped if - * it was running, and it will no longer be accessible through the download manager. If a file - * was already downloaded to external storage, it will not be deleted. + * it was running, and it will no longer be accessible through the download manager. + * If there is a downloaded file, partial or complete, it is deleted. * * @param ids the IDs of the downloads to remove * @return the number of downloads actually removed diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java index 52b310840276..d8d0a5b4f428 100644 --- a/core/java/android/app/FragmentManager.java +++ b/core/java/android/app/FragmentManager.java @@ -167,10 +167,9 @@ public abstract class FragmentManager { public static final int POP_BACK_STACK_INCLUSIVE = 1<<0; /** - * Pop the top state off the back stack. Returns true if there was one - * to pop, else false. This function is asynchronous -- it enqueues the - * request to pop, but the action will not be performed until the application - * returns to its event loop. + * Pop the top state off the back stack. This function is asynchronous -- it + * enqueues the request to pop, but the action will not be performed until the + * application returns to its event loop. */ public abstract void popBackStack(); diff --git a/core/java/android/appwidget/AppWidgetProviderInfo.java b/core/java/android/appwidget/AppWidgetProviderInfo.java index 32c239755040..b46802e94e7a 100644 --- a/core/java/android/appwidget/AppWidgetProviderInfo.java +++ b/core/java/android/appwidget/AppWidgetProviderInfo.java @@ -130,6 +130,9 @@ public class AppWidgetProviderInfo implements Parcelable { /** * The view id of the AppWidget subview which should be auto-advanced by the widget's host. + * + * <p>This field corresponds to the <code>android:autoAdvanceViewId</code> attribute in + * the AppWidget meta-data file. */ public int autoAdvanceViewId; @@ -146,8 +149,11 @@ public class AppWidgetProviderInfo implements Parcelable { * The rules by which a widget can be resized. See {@link #RESIZE_NONE}, * {@link #RESIZE_NONE}, {@link #RESIZE_HORIZONTAL}, * {@link #RESIZE_VERTICAL}, {@link #RESIZE_BOTH}. + * + * <p>This field corresponds to the <code>android:resizeMode</code> attribute in + * the AppWidget meta-data file. */ - public int resizableMode; + public int resizeMode; public AppWidgetProviderInfo() { } @@ -170,7 +176,7 @@ public class AppWidgetProviderInfo implements Parcelable { this.icon = in.readInt(); this.previewImage = in.readInt(); this.autoAdvanceViewId = in.readInt(); - this.resizableMode = in.readInt(); + this.resizeMode = in.readInt(); } public void writeToParcel(android.os.Parcel out, int flags) { @@ -194,7 +200,7 @@ public class AppWidgetProviderInfo implements Parcelable { out.writeInt(this.icon); out.writeInt(this.previewImage); out.writeInt(this.autoAdvanceViewId); - out.writeInt(this.resizableMode); + out.writeInt(this.resizeMode); } public int describeContents() { diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java index 61d74248c6be..06c1ecbc020b 100644 --- a/core/java/android/content/IntentFilter.java +++ b/core/java/android/content/IntentFilter.java @@ -1094,7 +1094,7 @@ public class IntentFilter implements Parcelable { */ public final int match(String action, String type, String scheme, Uri data, Set<String> categories, String logTag) { - if (!matchAction(action)) { + if (action != null && !matchAction(action)) { if (Config.LOGV) Log.v( logTag, "No matching action " + action + " for " + this); return NO_MATCH_ACTION; diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a58921622ae4..752574997a6e 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -785,6 +785,21 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device supports connecting to USB devices + * as the USB host. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_USB_HOST = "android.hardware.usb.host"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device supports connecting to USB accessories. + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_USB_ACCESSORY = "android.hardware.usb.accessory"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The SIP API is enabled on the device. */ @SdkConstant(SdkConstantType.FEATURE) diff --git a/core/java/android/hardware/IUsbManager.aidl b/core/java/android/hardware/IUsbManager.aidl index 6c99ab36fb03..8086f374df44 100644 --- a/core/java/android/hardware/IUsbManager.aidl +++ b/core/java/android/hardware/IUsbManager.aidl @@ -17,6 +17,7 @@ package android.hardware; import android.hardware.UsbAccessory; +import android.hardware.UsbDevice; import android.os.Bundle; import android.os.ParcelFileDescriptor; @@ -25,7 +26,39 @@ interface IUsbManager { /* Returns a list of all currently attached USB devices */ void getDeviceList(out Bundle devices); + + /* Returns a file descriptor for communicating with the USB device. + * The native fd can be passed to usb_device_new() in libusbhost. + */ ParcelFileDescriptor openDevice(String deviceName); + + /* Returns the currently attached USB accessory */ UsbAccessory getCurrentAccessory(); - ParcelFileDescriptor openAccessory(); + + /* Returns a file descriptor for communicating with the USB accessory. + * This file descriptor can be used with standard Java file operations. + */ + ParcelFileDescriptor openAccessory(in UsbAccessory accessory); + + /* Sets the default package for a USB device + * (or clears it if the package name is null) + */ + oneway void setDevicePackage(in UsbDevice device, String packageName); + + /* Sets the default package for a USB device + * (or clears it if the package name is null) + */ + void setAccessoryPackage(in UsbAccessory accessory, String packageName); + + /* Grants permission for the given UID to access the device */ + void grantDevicePermission(in UsbDevice device, int uid); + + /* Grants permission for the given UID to access the accessory */ + void grantAccessoryPermission(in UsbAccessory accessory, int uid); + + /* Returns true if the USB manager has default preferences or permissions for the package */ + boolean hasDefaults(String packageName, int uid); + + /* Clears default preferences and permissions for the package */ + oneway void clearDefaults(String packageName, int uid); } diff --git a/core/java/android/hardware/UsbAccessory.java b/core/java/android/hardware/UsbAccessory.java index 71672fa5517c..15dff3e03020 100644 --- a/core/java/android/hardware/UsbAccessory.java +++ b/core/java/android/hardware/UsbAccessory.java @@ -95,6 +95,23 @@ public final class UsbAccessory implements Parcelable { return mVersion; } + private static boolean compare(String s1, String s2) { + if (s1 == null) return (s2 == null); + return s1.equals(s2); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof UsbAccessory) { + UsbAccessory accessory = (UsbAccessory)obj; + return (compare(mManufacturer, accessory.getManufacturer()) && + compare(mModel, accessory.getModel()) && + compare(mType, accessory.getType()) && + compare(mVersion, accessory.getVersion())); + } + return false; + } + @Override public String toString() { return "UsbAccessory[mManufacturer=" + mManufacturer + diff --git a/core/java/android/hardware/UsbManager.java b/core/java/android/hardware/UsbManager.java index dcfdcf425c95..e9a34eac34f3 100644 --- a/core/java/android/hardware/UsbManager.java +++ b/core/java/android/hardware/UsbManager.java @@ -98,7 +98,7 @@ public class UsbManager { * * This intent is sent when a USB accessory is detached. * <ul> - * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory} + * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.UsbAccessory} * for the attached accessory that was detached * </ul> */ @@ -163,14 +163,15 @@ public class UsbManager { /** * Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and - * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts. + * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts * containing the UsbDevice object for the device. */ public static final String EXTRA_DEVICE = "device"; /** - * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} broadcast + * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} and + * {@link #ACTION_USB_ACCESSORY_DETACHED} broadcasts * containing the UsbAccessory object for the accessory. */ public static final String EXTRA_ACCESSORY = "accessory"; @@ -244,7 +245,7 @@ public class UsbManager { return new UsbAccessory[] { accessory }; } } catch (RemoteException e) { - Log.e(TAG, "RemoteException in openAccessory" , e); + Log.e(TAG, "RemoteException in getAccessoryList" , e); return null; } } @@ -257,7 +258,7 @@ public class UsbManager { */ public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { try { - return mService.openAccessory(); + return mService.openAccessory(accessory); } catch (RemoteException e) { Log.e(TAG, "RemoteException in openAccessory" , e); return null; diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 31f87198878a..8944f12e6e80 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -31,6 +31,7 @@ import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -356,7 +357,7 @@ public final class Parcel { public final native void enforceInterface(String interfaceName); /** - * Write a byte array into the parcel at the current {#link #dataPosition}, + * Write a byte array into the parcel at the current {@link #dataPosition}, * growing {@link #dataCapacity} if needed. * @param b Bytes to place into the parcel. */ @@ -365,7 +366,7 @@ public final class Parcel { } /** - * Write an byte array into the parcel at the current {#link #dataPosition}, + * Write an byte array into the parcel at the current {@link #dataPosition}, * growing {@link #dataCapacity} if needed. * @param b Bytes to place into the parcel. * @param offset Index of first byte to be written. @@ -376,9 +377,7 @@ public final class Parcel { writeInt(-1); return; } - if (b.length < offset + len || len < 0 || offset < 0) { - throw new ArrayIndexOutOfBoundsException(); - } + Arrays.checkOffsetAndCount(b.length, offset, len); writeNative(b, offset, len); } diff --git a/core/java/android/text/format/DateUtils.java b/core/java/android/text/format/DateUtils.java index a95dad79b112..353b628e7d70 100644 --- a/core/java/android/text/format/DateUtils.java +++ b/core/java/android/text/format/DateUtils.java @@ -642,14 +642,18 @@ public class DateUtils private static void initFormatStrings() { synchronized (sLock) { - Resources r = Resources.getSystem(); - Configuration cfg = r.getConfiguration(); - if (sLastConfig == null || !sLastConfig.equals(cfg)) { - sLastConfig = cfg; - sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT); - sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss); - sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss); - } + initFormatStringsLocked(); + } + } + + private static void initFormatStringsLocked() { + Resources r = Resources.getSystem(); + Configuration cfg = r.getConfiguration(); + if (sLastConfig == null || !sLastConfig.equals(cfg)) { + sLastConfig = cfg; + sStatusTimeFormat = java.text.DateFormat.getTimeInstance(java.text.DateFormat.SHORT); + sElapsedFormatMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_mm_ss); + sElapsedFormatHMMSS = r.getString(com.android.internal.R.string.elapsed_time_short_format_h_mm_ss); } } @@ -659,8 +663,10 @@ public class DateUtils * @hide */ public static final CharSequence timeString(long millis) { - initFormatStrings(); - return sStatusTimeFormat.format(millis); + synchronized (sLock) { + initFormatStringsLocked(); + return sStatusTimeFormat.format(millis); + } } /** diff --git a/core/java/android/text/method/BaseKeyListener.java b/core/java/android/text/method/BaseKeyListener.java index 191c250aa6b6..7e29dc76e401 100644 --- a/core/java/android/text/method/BaseKeyListener.java +++ b/core/java/android/text/method/BaseKeyListener.java @@ -33,23 +33,6 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener implements KeyListener { /* package */ static final Object OLD_SEL_START = new NoCopySpan.Concrete(); - private static final int MODIFIER_NONE = 0; - private static final int MODIFIER_ALT = 1; - private static final int MODIFIER_INVALID = 2; - - private static int getModifier(Editable content, KeyEvent event) { - if (event.hasModifiers(KeyEvent.META_ALT_ON)) { - return MODIFIER_ALT; - } - if (!event.hasNoModifiers()) { - return MODIFIER_INVALID; - } - if (getMetaState(content, META_ALT_ON) == 1) { - return MODIFIER_ALT; - } - return MODIFIER_NONE; - } - /** * Performs the action that happens when you press the {@link KeyEvent#KEYCODE_DEL} key in * a {@link TextView}. If there is a selection, deletes the selection; otherwise, @@ -59,27 +42,7 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener * @return true if anything was deleted; false otherwise. */ public boolean backspace(View view, Editable content, int keyCode, KeyEvent event) { - int modifier = getModifier(content, event); - if (modifier == MODIFIER_INVALID) { - return false; - } - - if (deleteSelection(view, content)) { - return true; - } - - if (modifier == MODIFIER_ALT && deleteLine(view, content)) { - return true; - } - - final int start = Selection.getSelectionEnd(content); - final int end = TextUtils.getOffsetBefore(content, start); - if (start != end) { - content.delete(Math.min(start, end), Math.max(start, end)); - return true; - } - - return false; + return backspaceOrForwardDelete(view, content, keyCode, event, false); } /** @@ -91,26 +54,42 @@ public abstract class BaseKeyListener extends MetaKeyKeyListener * @return true if anything was deleted; false otherwise. */ public boolean forwardDelete(View view, Editable content, int keyCode, KeyEvent event) { - int modifier = getModifier(content, event); - if (modifier == MODIFIER_INVALID) { + return backspaceOrForwardDelete(view, content, keyCode, event, true); + } + + private boolean backspaceOrForwardDelete(View view, Editable content, int keyCode, + KeyEvent event, boolean isForwardDelete) { + // Ensure the key event does not have modifiers except ALT or SHIFT. + if (!KeyEvent.metaStateHasNoModifiers(event.getMetaState() + & ~(KeyEvent.META_SHIFT_MASK | KeyEvent.META_ALT_MASK))) { return false; } + // If there is a current selection, delete it. if (deleteSelection(view, content)) { return true; } - if (modifier == MODIFIER_ALT && deleteLine(view, content)) { - return true; + // Alt+Backspace or Alt+ForwardDelete deletes the current line, if possible. + if (event.isAltPressed() || getMetaState(content, META_ALT_ON) == 1) { + if (deleteLine(view, content)) { + return true; + } } + // Delete a character. final int start = Selection.getSelectionEnd(content); - final int end = TextUtils.getOffsetAfter(content, start); + final int end; + if (isForwardDelete || event.isShiftPressed() + || getMetaState(content, META_SHIFT_ON) == 1) { + end = TextUtils.getOffsetAfter(content, start); + } else { + end = TextUtils.getOffsetBefore(content, start); + } if (start != end) { content.delete(Math.min(start, end), Math.max(start, end)); return true; } - return false; } diff --git a/core/java/android/text/method/BaseMovementMethod.java b/core/java/android/text/method/BaseMovementMethod.java index 2be18d674816..94c6ed08c1e1 100644 --- a/core/java/android/text/method/BaseMovementMethod.java +++ b/core/java/android/text/method/BaseMovementMethod.java @@ -18,6 +18,7 @@ package android.text.method; import android.text.Layout; import android.text.Spannable; +import android.view.InputDevice; import android.view.KeyEvent; import android.view.MotionEvent; import android.widget.TextView; @@ -88,6 +89,39 @@ public class BaseMovementMethod implements MovementMethod { return false; } + @Override + public boolean onGenericMotionEvent(TextView widget, Spannable text, MotionEvent event) { + if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { + switch (event.getAction()) { + case MotionEvent.ACTION_SCROLL: { + final float vscroll; + final float hscroll; + if ((event.getMetaState() & KeyEvent.META_SHIFT_ON) != 0) { + vscroll = 0; + hscroll = event.getAxisValue(MotionEvent.AXIS_VSCROLL); + } else { + vscroll = -event.getAxisValue(MotionEvent.AXIS_VSCROLL); + hscroll = event.getAxisValue(MotionEvent.AXIS_HSCROLL); + } + + boolean handled = false; + if (hscroll < 0) { + handled |= scrollLeft(widget, text, (int)Math.ceil(-hscroll)); + } else if (hscroll > 0) { + handled |= scrollRight(widget, text, (int)Math.ceil(hscroll)); + } + if (vscroll < 0) { + handled |= scrollUp(widget, text, (int)Math.ceil(-vscroll)); + } else if (vscroll > 0) { + handled |= scrollDown(widget, text, (int)Math.ceil(vscroll)); + } + return handled; + } + } + } + return false; + } + /** * Gets the meta state used for movement using the modifiers tracked by the text * buffer as well as those present in the key event. @@ -342,4 +376,276 @@ public class BaseMovementMethod implements MovementMethod { protected boolean end(TextView widget, Spannable buffer) { return false; } + + private int getTopLine(TextView widget) { + return widget.getLayout().getLineForVertical(widget.getScrollY()); + } + + private int getBottomLine(TextView widget) { + return widget.getLayout().getLineForVertical(widget.getScrollY() + getInnerHeight(widget)); + } + + private int getInnerWidth(TextView widget) { + return widget.getWidth() - widget.getTotalPaddingLeft() - widget.getTotalPaddingRight(); + } + + private int getInnerHeight(TextView widget) { + return widget.getHeight() - widget.getTotalPaddingTop() - widget.getTotalPaddingBottom(); + } + + private int getCharacterWidth(TextView widget) { + return (int) Math.ceil(widget.getPaint().getFontSpacing()); + } + + private int getScrollBoundsLeft(TextView widget) { + final Layout layout = widget.getLayout(); + final int topLine = getTopLine(widget); + final int bottomLine = getBottomLine(widget); + if (topLine > bottomLine) { + return 0; + } + int left = Integer.MAX_VALUE; + for (int line = topLine; line <= bottomLine; line++) { + final int lineLeft = (int) Math.floor(layout.getLineLeft(line)); + if (lineLeft < left) { + left = lineLeft; + } + } + return left; + } + + private int getScrollBoundsRight(TextView widget) { + final Layout layout = widget.getLayout(); + final int topLine = getTopLine(widget); + final int bottomLine = getBottomLine(widget); + if (topLine > bottomLine) { + return 0; + } + int right = Integer.MIN_VALUE; + for (int line = topLine; line <= bottomLine; line++) { + final int lineRight = (int) Math.ceil(layout.getLineRight(line)); + if (lineRight > right) { + right = lineRight; + } + } + return right; + } + + /** + * Performs a scroll left action. + * Scrolls left by the specified number of characters. + * + * @param widget The text view. + * @param buffer The text buffer. + * @param amount The number of characters to scroll by. Must be at least 1. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollLeft(TextView widget, Spannable buffer, int amount) { + final int minScrollX = getScrollBoundsLeft(widget); + int scrollX = widget.getScrollX(); + if (scrollX > minScrollX) { + scrollX = Math.max(scrollX - getCharacterWidth(widget) * amount, minScrollX); + widget.scrollTo(scrollX, widget.getScrollY()); + return true; + } + return false; + } + + /** + * Performs a scroll right action. + * Scrolls right by the specified number of characters. + * + * @param widget The text view. + * @param buffer The text buffer. + * @param amount The number of characters to scroll by. Must be at least 1. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollRight(TextView widget, Spannable buffer, int amount) { + final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget); + int scrollX = widget.getScrollX(); + if (scrollX < maxScrollX) { + scrollX = Math.min(scrollX + getCharacterWidth(widget) * amount, maxScrollX); + widget.scrollTo(scrollX, widget.getScrollY()); + return true; + } + return false; + } + + /** + * Performs a scroll up action. + * Scrolls up by the specified number of lines. + * + * @param widget The text view. + * @param buffer The text buffer. + * @param amount The number of lines to scroll by. Must be at least 1. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollUp(TextView widget, Spannable buffer, int amount) { + final Layout layout = widget.getLayout(); + final int top = widget.getScrollY(); + int topLine = layout.getLineForVertical(top); + if (layout.getLineTop(topLine) == top) { + // If the top line is partially visible, bring it all the way + // into view; otherwise, bring the previous line into view. + topLine -= 1; + } + if (topLine >= 0) { + topLine = Math.max(topLine - amount + 1, 0); + Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine)); + return true; + } + return false; + } + + /** + * Performs a scroll down action. + * Scrolls down by the specified number of lines. + * + * @param widget The text view. + * @param buffer The text buffer. + * @param amount The number of lines to scroll by. Must be at least 1. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollDown(TextView widget, Spannable buffer, int amount) { + final Layout layout = widget.getLayout(); + final int innerHeight = getInnerHeight(widget); + final int bottom = widget.getScrollY() + innerHeight; + int bottomLine = layout.getLineForVertical(bottom); + if (layout.getLineTop(bottomLine + 1) < bottom + 1) { + // Less than a pixel of this line is out of view, + // so we must have tried to make it entirely in view + // and now want the next line to be in view instead. + bottomLine += 1; + } + final int limit = layout.getLineCount() - 1; + if (bottomLine <= limit) { + bottomLine = Math.min(bottomLine + amount - 1, limit); + Touch.scrollTo(widget, layout, widget.getScrollX(), + layout.getLineTop(bottomLine + 1) - innerHeight); + return true; + } + return false; + } + + /** + * Performs a scroll page up action. + * Scrolls up by one page. + * + * @param widget The text view. + * @param buffer The text buffer. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollPageUp(TextView widget, Spannable buffer) { + final Layout layout = widget.getLayout(); + final int top = widget.getScrollY() - getInnerHeight(widget); + int topLine = layout.getLineForVertical(top); + if (topLine >= 0) { + Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine)); + return true; + } + return false; + } + + /** + * Performs a scroll page up action. + * Scrolls down by one page. + * + * @param widget The text view. + * @param buffer The text buffer. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollPageDown(TextView widget, Spannable buffer) { + final Layout layout = widget.getLayout(); + final int innerHeight = getInnerHeight(widget); + final int bottom = widget.getScrollY() + innerHeight + innerHeight; + int bottomLine = layout.getLineForVertical(bottom); + if (bottomLine <= layout.getLineCount() - 1) { + Touch.scrollTo(widget, layout, widget.getScrollX(), + layout.getLineTop(bottomLine + 1) - innerHeight); + return true; + } + return false; + } + + /** + * Performs a scroll to top action. + * Scrolls to the top of the document. + * + * @param widget The text view. + * @param buffer The text buffer. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollTop(TextView widget, Spannable buffer) { + final Layout layout = widget.getLayout(); + if (getTopLine(widget) >= 0) { + Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(0)); + return true; + } + return false; + } + + /** + * Performs a scroll to bottom action. + * Scrolls to the bottom of the document. + * + * @param widget The text view. + * @param buffer The text buffer. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollBottom(TextView widget, Spannable buffer) { + final Layout layout = widget.getLayout(); + final int lineCount = layout.getLineCount(); + if (getBottomLine(widget) <= lineCount - 1) { + Touch.scrollTo(widget, layout, widget.getScrollX(), + layout.getLineTop(lineCount) - getInnerHeight(widget)); + return true; + } + return false; + } + + /** + * Performs a scroll to line start action. + * Scrolls to the start of the line. + * + * @param widget The text view. + * @param buffer The text buffer. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollLineStart(TextView widget, Spannable buffer) { + final int minScrollX = getScrollBoundsLeft(widget); + int scrollX = widget.getScrollX(); + if (scrollX > minScrollX) { + widget.scrollTo(minScrollX, widget.getScrollY()); + return true; + } + return false; + } + + /** + * Performs a scroll to line end action. + * Scrolls to the end of the line. + * + * @param widget The text view. + * @param buffer The text buffer. + * @return True if the event was handled. + * @hide + */ + protected boolean scrollLineEnd(TextView widget, Spannable buffer) { + final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget); + int scrollX = widget.getScrollX(); + if (scrollX < maxScrollX) { + widget.scrollTo(maxScrollX, widget.getScrollY()); + return true; + } + return false; + } } diff --git a/core/java/android/text/method/MovementMethod.java b/core/java/android/text/method/MovementMethod.java index 91676766d2c4..01979fdb5cd4 100644 --- a/core/java/android/text/method/MovementMethod.java +++ b/core/java/android/text/method/MovementMethod.java @@ -47,6 +47,7 @@ public interface MovementMethod { public void onTakeFocus(TextView widget, Spannable text, int direction); public boolean onTrackballEvent(TextView widget, Spannable text, MotionEvent event); public boolean onTouchEvent(TextView widget, Spannable text, MotionEvent event); + public boolean onGenericMotionEvent(TextView widget, Spannable text, MotionEvent event); /** * Returns true if this movement method allows arbitrary selection diff --git a/core/java/android/text/method/ScrollingMovementMethod.java b/core/java/android/text/method/ScrollingMovementMethod.java index 194ecc128eae..b9f5d5f447e3 100644 --- a/core/java/android/text/method/ScrollingMovementMethod.java +++ b/core/java/android/text/method/ScrollingMovementMethod.java @@ -25,189 +25,54 @@ import android.view.View; * A movement method that interprets movement keys by scrolling the text buffer. */ public class ScrollingMovementMethod extends BaseMovementMethod implements MovementMethod { - private int getTopLine(TextView widget) { - return widget.getLayout().getLineForVertical(widget.getScrollY()); - } - - private int getBottomLine(TextView widget) { - return widget.getLayout().getLineForVertical(widget.getScrollY() + getInnerHeight(widget)); - } - - private int getInnerWidth(TextView widget) { - return widget.getWidth() - widget.getTotalPaddingLeft() - widget.getTotalPaddingRight(); - } - - private int getInnerHeight(TextView widget) { - return widget.getHeight() - widget.getTotalPaddingTop() - widget.getTotalPaddingBottom(); - } - - private int getCharacterWidth(TextView widget) { - return (int) Math.ceil(widget.getPaint().getFontSpacing()); - } - - private int getScrollBoundsLeft(TextView widget) { - final Layout layout = widget.getLayout(); - final int topLine = getTopLine(widget); - final int bottomLine = getBottomLine(widget); - if (topLine > bottomLine) { - return 0; - } - int left = Integer.MAX_VALUE; - for (int line = topLine; line <= bottomLine; line++) { - final int lineLeft = (int) Math.floor(layout.getLineLeft(line)); - if (lineLeft < left) { - left = lineLeft; - } - } - return left; - } - - private int getScrollBoundsRight(TextView widget) { - final Layout layout = widget.getLayout(); - final int topLine = getTopLine(widget); - final int bottomLine = getBottomLine(widget); - if (topLine > bottomLine) { - return 0; - } - int right = Integer.MIN_VALUE; - for (int line = topLine; line <= bottomLine; line++) { - final int lineRight = (int) Math.ceil(layout.getLineRight(line)); - if (lineRight > right) { - right = lineRight; - } - } - return right; - } - @Override protected boolean left(TextView widget, Spannable buffer) { - final int minScrollX = getScrollBoundsLeft(widget); - int scrollX = widget.getScrollX(); - if (scrollX > minScrollX) { - scrollX = Math.max(scrollX - getCharacterWidth(widget), minScrollX); - widget.scrollTo(scrollX, widget.getScrollY()); - return true; - } - return false; + return scrollLeft(widget, buffer, 1); } @Override protected boolean right(TextView widget, Spannable buffer) { - final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget); - int scrollX = widget.getScrollX(); - if (scrollX < maxScrollX) { - scrollX = Math.min(scrollX + getCharacterWidth(widget), maxScrollX); - widget.scrollTo(scrollX, widget.getScrollY()); - return true; - } - return false; + return scrollRight(widget, buffer, 1); } @Override protected boolean up(TextView widget, Spannable buffer) { - final Layout layout = widget.getLayout(); - final int top = widget.getScrollY(); - int topLine = layout.getLineForVertical(top); - if (layout.getLineTop(topLine) == top) { - // If the top line is partially visible, bring it all the way - // into view; otherwise, bring the previous line into view. - topLine -= 1; - } - if (topLine >= 0) { - Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine)); - return true; - } - return false; + return scrollUp(widget, buffer, 1); } @Override protected boolean down(TextView widget, Spannable buffer) { - final Layout layout = widget.getLayout(); - final int innerHeight = getInnerHeight(widget); - final int bottom = widget.getScrollY() + innerHeight; - int bottomLine = layout.getLineForVertical(bottom); - if (layout.getLineTop(bottomLine + 1) < bottom + 1) { - // Less than a pixel of this line is out of view, - // so we must have tried to make it entirely in view - // and now want the next line to be in view instead. - bottomLine += 1; - } - if (bottomLine <= layout.getLineCount() - 1) { - Touch.scrollTo(widget, layout, widget.getScrollX(), - layout.getLineTop(bottomLine + 1) - innerHeight); - return true; - } - return false; + return scrollDown(widget, buffer, 1); } @Override protected boolean pageUp(TextView widget, Spannable buffer) { - final Layout layout = widget.getLayout(); - final int top = widget.getScrollY() - getInnerHeight(widget); - int topLine = layout.getLineForVertical(top); - if (topLine >= 0) { - Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(topLine)); - return true; - } - return false; + return scrollPageUp(widget, buffer); } @Override protected boolean pageDown(TextView widget, Spannable buffer) { - final Layout layout = widget.getLayout(); - final int innerHeight = getInnerHeight(widget); - final int bottom = widget.getScrollY() + innerHeight + innerHeight; - int bottomLine = layout.getLineForVertical(bottom); - if (bottomLine <= layout.getLineCount() - 1) { - Touch.scrollTo(widget, layout, widget.getScrollX(), - layout.getLineTop(bottomLine + 1) - innerHeight); - return true; - } - return false; + return scrollPageDown(widget, buffer); } @Override protected boolean top(TextView widget, Spannable buffer) { - final Layout layout = widget.getLayout(); - if (getTopLine(widget) >= 0) { - Touch.scrollTo(widget, layout, widget.getScrollX(), layout.getLineTop(0)); - return true; - } - return false; + return scrollTop(widget, buffer); } @Override protected boolean bottom(TextView widget, Spannable buffer) { - final Layout layout = widget.getLayout(); - final int lineCount = layout.getLineCount(); - if (getBottomLine(widget) <= lineCount - 1) { - Touch.scrollTo(widget, layout, widget.getScrollX(), - layout.getLineTop(lineCount) - getInnerHeight(widget)); - return true; - } - return false; + return scrollBottom(widget, buffer); } @Override protected boolean lineStart(TextView widget, Spannable buffer) { - final int minScrollX = getScrollBoundsLeft(widget); - int scrollX = widget.getScrollX(); - if (scrollX > minScrollX) { - widget.scrollTo(minScrollX, widget.getScrollY()); - return true; - } - return false; + return scrollLineStart(widget, buffer); } @Override protected boolean lineEnd(TextView widget, Spannable buffer) { - final int maxScrollX = getScrollBoundsRight(widget) - getInnerWidth(widget); - int scrollX = widget.getScrollX(); - if (scrollX < maxScrollX) { - widget.scrollTo(maxScrollX, widget.getScrollY()); - return true; - } - return false; + return scrollLineEnd(widget, buffer); } @Override diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java index d7b0dc14bddc..904250566357 100644 --- a/core/java/android/util/TimeUtils.java +++ b/core/java/android/util/TimeUtils.java @@ -191,7 +191,7 @@ public class TimeUtils { int pos = 0; fieldLen -= 1; while (pos < fieldLen) { - formatStr[pos] = ' '; + formatStr[pos++] = ' '; } formatStr[pos] = '0'; return pos+1; diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java index b74806486bf9..126f409d1dab 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -79,6 +79,11 @@ public class Display */ native public int getHeight(); + /** @hide special for when we are faking the screen size. */ + native public int getRealWidth(); + /** @hide special for when we are faking the screen size. */ + native public int getRealHeight(); + /** * Returns the rotation of the screen from its "natural" orientation. * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} @@ -136,11 +141,6 @@ public class Display outMetrics.ydpi = mDpiY; } - /** - * @hide Helper for our fake display size hack. - */ - native public static int unmapDisplaySize(int newSize); - /* * We use a class initializer to allow the native code to cache some * field offsets. diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index 218ee4f9885a..0124151b5ddc 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -245,6 +245,7 @@ public class ScaleGestureDetector { final float bottomSlop = mBottomSlopEdge; int index0 = event.findPointerIndex(mActiveId0); int index1 = event.findPointerIndex(mActiveId1); + float x0 = getRawX(event, index0); float y0 = getRawY(event, index0); float x1 = getRawX(event, index1); @@ -353,14 +354,24 @@ public class ScaleGestureDetector { if (actionId == mActiveId0) { final int newIndex = findNewActiveIndex(event, mActiveId1, actionIndex); if (newIndex >= 0) { + mListener.onScaleEnd(this); mActiveId0 = event.getPointerId(newIndex); + mActive0MostRecent = true; + mPrevEvent = MotionEvent.obtain(event); + setContext(event); + mGestureInProgress = mListener.onScaleBegin(this); } else { gestureEnded = true; } } else if (actionId == mActiveId1) { final int newIndex = findNewActiveIndex(event, mActiveId0, actionIndex); if (newIndex >= 0) { + mListener.onScaleEnd(this); mActiveId1 = event.getPointerId(newIndex); + mActive0MostRecent = false; + mPrevEvent = MotionEvent.obtain(event); + setContext(event); + mGestureInProgress = mListener.onScaleBegin(this); } else { gestureEnded = true; } @@ -449,6 +460,7 @@ public class ScaleGestureDetector { * MotionEvent has no getRawX(int) method; simulate it pending future API approval. */ private static float getRawX(MotionEvent event, int pointerIndex) { + if (pointerIndex < 0) return Float.MIN_VALUE; if (pointerIndex == 0) return event.getRawX(); float offset = event.getRawX() - event.getX(); return event.getX(pointerIndex) + offset; @@ -458,6 +470,7 @@ public class ScaleGestureDetector { * MotionEvent has no getRawY(int) method; simulate it pending future API approval. */ private static float getRawY(MotionEvent event, int pointerIndex) { + if (pointerIndex < 0) return Float.MIN_VALUE; if (pointerIndex == 0) return event.getRawY(); float offset = event.getRawY() - event.getY(); return event.getY(pointerIndex) + offset; diff --git a/core/java/android/webkit/HTML5Audio.java b/core/java/android/webkit/HTML5Audio.java index a3906ddb76c4..6fc0d119f9c9 100644 --- a/core/java/android/webkit/HTML5Audio.java +++ b/core/java/android/webkit/HTML5Audio.java @@ -173,7 +173,8 @@ class HTML5Audio extends Handler mState = INITIALIZED; mMediaPlayer.prepareAsync(); } catch (IOException e) { - Log.e(LOGTAG, "couldn't load the resource: " + url + " exc: " + e); + String debugUrl = url.length() > 128 ? url.substring(0, 128) + "..." : url; + Log.e(LOGTAG, "couldn't load the resource: "+ debugUrl +" exc: " + e); resetMediaPlayer(); } } diff --git a/core/java/android/webkit/L10nUtils.java b/core/java/android/webkit/L10nUtils.java index 962492e08de6..f59d7d0d6a08 100644 --- a/core/java/android/webkit/L10nUtils.java +++ b/core/java/android/webkit/L10nUtils.java @@ -18,8 +18,9 @@ package android.webkit; import android.content.Context; -import java.util.List; -import java.util.Vector; +import java.lang.ref.SoftReference; +import java.util.Map; +import java.util.HashMap; /** * @hide @@ -32,23 +33,71 @@ public class L10nUtils { com.android.internal.R.string.autofill_address_name_separator, // IDS_AUTOFILL_DIALOG_ADDRESS_NAME_SEPARATOR com.android.internal.R.string.autofill_address_summary_name_format, // IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_NAME_FORMAT com.android.internal.R.string.autofill_address_summary_separator, // IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_SEPARATOR - com.android.internal.R.string.autofill_address_summary_format // IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FORMAT + com.android.internal.R.string.autofill_address_summary_format, // IDS_AUTOFILL_DIALOG_ADDRESS_SUMMARY_FORMAT + com.android.internal.R.string.autofill_attention_ignored_re, // IDS_AUTOFILL_ATTENTION_IGNORED_RE + com.android.internal.R.string.autofill_region_ignored_re, // IDS_AUTOFILL_REGION_IGNORED_RE + com.android.internal.R.string.autofill_company_re, // IDS_AUTOFILL_COMPANY_RE + com.android.internal.R.string.autofill_address_line_1_re, // IDS_AUTOFILL_ADDRESS_LINE_1_RE + com.android.internal.R.string.autofill_address_line_1_label_re, // IDS_AUTOFILL_ADDRESS_LINE_1_LABEL_RE + com.android.internal.R.string.autofill_address_line_2_re, // IDS_AUTOFILL_ADDRESS_LINE_2_RE + com.android.internal.R.string.autofill_address_line_3_re, // IDS_AUTOFILL_ADDRESS_LINE_3_RE + com.android.internal.R.string.autofill_country_re, // IDS_AUTOFILL_COUNTRY_RE + com.android.internal.R.string.autofill_zip_code_re, // IDS_AUTOFILL_ZIP_CODE_RE + com.android.internal.R.string.autofill_zip_4_re, // IDS_AUTOFILL_ZIP_4_RE + com.android.internal.R.string.autofill_city_re, // IDS_AUTOFILL_CITY_RE + com.android.internal.R.string.autofill_state_re, // IDS_AUTOFILL_STATE_RE + com.android.internal.R.string.autofill_address_type_same_as_re, // IDS_AUTOFILL_SAME_AS_RE + com.android.internal.R.string.autofill_address_type_use_my_re, // IDS_AUTOFILL_USE_MY_RE + com.android.internal.R.string.autofill_billing_designator_re, // IDS_AUTOFILL_BILLING_DESIGNATOR_RE + com.android.internal.R.string.autofill_shipping_designator_re, // IDS_AUTOFILL_SHIPPING_DESIGNATOR_RE + com.android.internal.R.string.autofill_email_re, // IDS_AUTOFILL_EMAIL_RE + com.android.internal.R.string.autofill_username_re, // IDS_AUTOFILL_USERNAME_RE + com.android.internal.R.string.autofill_name_re, // IDS_AUTOFILL_NAME_RE + com.android.internal.R.string.autofill_name_specific_re, // IDS_AUTOFILL_NAME_SPECIFIC_RE + com.android.internal.R.string.autofill_first_name_re, // IDS_AUTOFILL_FIRST_NAME_RE + com.android.internal.R.string.autofill_middle_initial_re, // IDS_AUTOFILL_MIDDLE_INITIAL_RE + com.android.internal.R.string.autofill_middle_name_re, // IDS_AUTOFILL_MIDDLE_NAME_RE + com.android.internal.R.string.autofill_last_name_re, // IDS_AUTOFILL_LAST_NAME_RE + com.android.internal.R.string.autofill_phone_re, // IDS_AUTOFILL_PHONE_RE + com.android.internal.R.string.autofill_area_code_re, // IDS_AUTOFILL_AREA_CODE_RE + com.android.internal.R.string.autofill_phone_prefix_re, // IDS_AUTOFILL_PHONE_PREFIX_RE + com.android.internal.R.string.autofill_phone_suffix_re, // IDS_AUTOFILL_PHONE_SUFFIX_RE + com.android.internal.R.string.autofill_phone_extension_re, // IDS_AUTOFILL_PHONE_EXTENSION_RE + com.android.internal.R.string.autofill_name_on_card_re, // IDS_AUTOFILL_NAME_ON_CARD_RE + com.android.internal.R.string.autofill_name_on_card_contextual_re, // IDS_AUTOFILL_NAME_ON_CARD_CONTEXTUAL_RE + com.android.internal.R.string.autofill_card_cvc_re, // IDS_AUTOFILL_CARD_CVC_RE + com.android.internal.R.string.autofill_card_number_re, // IDS_AUTOFILL_CARD_NUMBER_RE + com.android.internal.R.string.autofill_expiration_month_re, // IDS_AUTOFILL_EXPIRATION_MONTH_RE + com.android.internal.R.string.autofill_expiration_date_re, // IDS_AUTOFILL_EXPIRATION_DATE_RE + com.android.internal.R.string.autofill_card_ignored_re // IDS_AUTOFILL_CARD_IGNORED_RE }; - private static List<String> mStrings; + private static Context mApplicationContext; + private static Map<Integer, SoftReference<String> > mStrings; - public static void loadStrings(Context context) { - if (mStrings != null) { - return; - } + public static void setApplicationContext(Context applicationContext) { + mApplicationContext = applicationContext.getApplicationContext(); + } - mStrings = new Vector<String>(mIdsArray.length); - for (int i = 0; i < mIdsArray.length; i++) { - mStrings.add(context.getResources().getString(mIdsArray[i])); + private static String loadString(int id) { + if (mStrings == null) { + mStrings = new HashMap<Integer, SoftReference<String> >(mIdsArray.length); } + + String localisedString = mApplicationContext.getResources().getString(mIdsArray[id]); + mStrings.put(id, new SoftReference<String>(localisedString)); + return localisedString; } public static String getLocalisedString(int id) { - return mStrings.get(id); + if (mStrings == null) { + // This is the first time we need a localised string. + // loadString will create the Map. + return loadString(id); + } + + SoftReference<String> ref = mStrings.get(id); + boolean needToLoad = ref == null || ref.get() == null; + return needToLoad ? loadString(id) : ref.get(); } } diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 98fc29022a93..f877fc850c42 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -987,7 +987,7 @@ public class WebView extends AbsoluteLayout mCallbackProxy = new CallbackProxy(context, this); mViewManager = new ViewManager(this); - L10nUtils.loadStrings(context); + L10nUtils.setApplicationContext(context.getApplicationContext()); mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces); mDatabase = WebViewDatabase.getInstance(context); mScroller = new OverScroller(context, null, 0, 0, false); //TODO Use OverScroller's flywheel @@ -7768,11 +7768,11 @@ public class WebView extends AbsoluteLayout * and allow filtering. */ private class MyArrayListAdapter extends ArrayAdapter<Container> { - public MyArrayListAdapter(Context context, Container[] objects, boolean multiple) { - super(context, - multiple ? com.android.internal.R.layout.select_dialog_multichoice : - com.android.internal.R.layout.select_dialog_singlechoice, - objects); + public MyArrayListAdapter() { + super(mContext, + mMultiple ? com.android.internal.R.layout.select_dialog_multichoice : + com.android.internal.R.layout.webview_select_singlechoice, + mContainers); } @Override @@ -7798,13 +7798,12 @@ public class WebView extends AbsoluteLayout } if (Container.OPTGROUP == c.mEnabled) { - // Currently select_dialog_multichoice and - // select_dialog_singlechoice are CheckedTextViews. If - // that changes, the class cast will no longer be valid. - Assert.assertTrue( - convertView instanceof CheckedTextView); - ((CheckedTextView) convertView).setCheckMarkDrawable( - null); + // Currently select_dialog_multichoice uses CheckedTextViews. + // If that changes, the class cast will no longer be valid. + if (mMultiple) { + Assert.assertTrue(convertView instanceof CheckedTextView); + ((CheckedTextView) convertView).setCheckMarkDrawable(null); + } } else { // c.mEnabled == Container.OPTION_DISABLED // Draw the disabled element in a disabled state. @@ -7911,6 +7910,7 @@ public class WebView extends AbsoluteLayout mAdapter = a; } + @Override public void onChanged() { // The filter may have changed which item is checked. Find the // item that the ListView thinks is checked. @@ -7931,15 +7931,12 @@ public class WebView extends AbsoluteLayout } } } - - public void onInvalidate() {} } public void run() { final ListView listView = (ListView) LayoutInflater.from(mContext) .inflate(com.android.internal.R.layout.select_dialog, null); - final MyArrayListAdapter adapter = new - MyArrayListAdapter(mContext, mContainers, mMultiple); + final MyArrayListAdapter adapter = new MyArrayListAdapter(); AlertDialog.Builder b = new AlertDialog.Builder(mContext) .setView(listView).setCancelable(true) .setInverseBackgroundForced(true); @@ -7977,7 +7974,7 @@ public class WebView extends AbsoluteLayout } } else { listView.setOnItemClickListener(new OnItemClickListener() { - public void onItemClick(AdapterView parent, View v, + public void onItemClick(AdapterView<?> parent, View v, int position, long id) { // Rather than sending the message right away, send it // after the page regains focus. diff --git a/core/java/android/webkit/ZoomManager.java b/core/java/android/webkit/ZoomManager.java index 5e0de27bb173..63038503b238 100644 --- a/core/java/android/webkit/ZoomManager.java +++ b/core/java/android/webkit/ZoomManager.java @@ -227,10 +227,13 @@ class ZoomManager { assert density > 0; if (Math.abs(density - mDefaultScale) > MINIMUM_SCALE_INCREMENT) { + // Remember the current zoom density before it gets changed. + final float originalDefault = mDefaultScale; // set the new default density setDefaultZoomScale(density); + float scaleChange = (originalDefault > 0.0) ? density / originalDefault: 1.0f; // adjust the scale if it falls outside the new zoom bounds - setZoomScale(mActualScale, true); + setZoomScale(mActualScale * scaleChange, true); } } @@ -721,10 +724,7 @@ class ZoomManager { } public boolean onScale(ScaleGestureDetector detector) { - // Prevent scaling beyond overview scale. - float scale = Math.max( - computeScaleWithLimits(detector.getScaleFactor() * mActualScale), - getZoomOverviewScale()); + float scale = computeScaleWithLimits(detector.getScaleFactor() * mActualScale); if (mPinchToZoomAnimating || willScaleTriggerZoom(scale)) { mPinchToZoomAnimating = true; // limit the scale change per step @@ -780,13 +780,6 @@ class ZoomManager { // update mMinZoomScale if the minimum zoom scale is not fixed if (!mMinZoomScaleFixed) { - // when change from narrow screen to wide screen, the new viewWidth - // can be wider than the old content width. We limit the minimum - // scale to 1.0f. The proper minimum scale will be calculated when - // the new picture shows up. - mMinZoomScale = Math.min(1.0f, (float) mWebView.getViewWidth() - / (mWebView.drawHistory() ? mWebView.getHistoryPictureWidth() - : mZoomOverviewWidth)); // limit the minZoomScale to the initialScale if it is set if (mInitialScale > 0 && mInitialScale < mMinZoomScale) { mMinZoomScale = mInitialScale; @@ -823,7 +816,7 @@ class ZoomManager { // Keep overview mode unchanged when rotating. final float zoomOverviewScale = getZoomOverviewScale(); final float newScale = (mInZoomOverviewBeforeSizeChange) ? - zoomOverviewScale : Math.max(mActualScale, zoomOverviewScale); + zoomOverviewScale : mActualScale; setZoomScale(newScale, mUpdateTextWrap, true); // update the zoom buttons as the scale can be changed updateZoomPicker(); @@ -879,21 +872,15 @@ class ZoomManager { } } - if (!mMinZoomScaleFixed) { - mMinZoomScale = newZoomOverviewScale; - } // fit the content width to the current view for the first new picture // after first layout. boolean scaleHasDiff = exceedsMinScaleIncrement(newZoomOverviewScale, mActualScale); - // Make sure the actual scale is no less than zoom overview scale. - boolean scaleLessThanOverview = - (newZoomOverviewScale - mActualScale) >= MINIMUM_SCALE_INCREMENT; // Make sure mobile sites are correctly handled since mobile site will // change content width after rotating. boolean mobileSiteInOverview = mInZoomOverview && !exceedsMinScaleIncrement(newZoomOverviewScale, 1.0f); if (!mWebView.drawHistory() && - (mInitialZoomOverview || scaleLessThanOverview || mobileSiteInOverview) && + (mInitialZoomOverview || mobileSiteInOverview) && scaleHasDiff && zoomOverviewWidthChanged) { mInitialZoomOverview = false; setZoomScale(newZoomOverviewScale, !willScaleTriggerZoom(mTextWrapScale) && @@ -967,10 +954,11 @@ class ZoomManager { mTextWrapScale = viewState.mTextWrapScale; scale = viewState.mViewScale; } else { - scale = overviewScale; - if (!settings.getUseWideViewPort() - || !settings.getLoadWithOverviewMode()) { - scale = Math.max(viewState.mTextWrapScale, scale); + scale = mDefaultScale; + mTextWrapScale = mDefaultScale; + if (settings.getUseWideViewPort() + && settings.getLoadWithOverviewMode()) { + scale = Math.max(overviewScale, scale); } if (settings.isNarrowColumnLayout() && settings.getUseFixedViewport()) { @@ -981,7 +969,7 @@ class ZoomManager { } boolean reflowText = false; if (!viewState.mIsRestored) { - if (settings.getUseFixedViewport()) { + if (settings.getUseFixedViewport() && settings.getLoadWithOverviewMode()) { // Override the scale only in case of fixed viewport. scale = Math.max(scale, overviewScale); mTextWrapScale = Math.max(mTextWrapScale, overviewScale); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 086089278d77..1a62f4edf66b 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -3529,6 +3529,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te post(this); } else { mTouchMode = TOUCH_MODE_REST; + reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE); } } diff --git a/core/java/android/widget/EdgeGlow.java b/core/java/android/widget/EdgeGlow.java index 2a0e8495eace..c2cb0a053659 100644 --- a/core/java/android/widget/EdgeGlow.java +++ b/core/java/android/widget/EdgeGlow.java @@ -339,6 +339,7 @@ public class EdgeGlow { mEdgeScaleY = mEdgeScaleYStart + (mEdgeScaleYFinish - mEdgeScaleYStart) * interp * factor; + mState = STATE_RECEDE; break; case STATE_RECEDE: mState = STATE_IDLE; diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 7a591782564f..2947ebeb1d4b 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -608,7 +608,7 @@ public class NumberPicker extends LinearLayout { case MotionEvent.ACTION_DOWN: mLastMotionEventY = mLastDownEventY = event.getY(); removeAllCallbacks(); - hideInputControls(); + mShowInputControlsAnimator.cancel(); mBeginEditOnUpEvent = false; mAdjustScrollerOnUpEvent = true; if (mDrawSelectorWheel) { @@ -621,6 +621,7 @@ public class NumberPicker extends LinearLayout { } mBeginEditOnUpEvent = scrollersFinished; mAdjustScrollerOnUpEvent = true; + hideInputControls(); return true; } if (isEventInViewHitRect(event, mInputText) @@ -630,6 +631,7 @@ public class NumberPicker extends LinearLayout { && isEventInViewHitRect(event, mDecrementButton))) { mAdjustScrollerOnUpEvent = false; setDrawSelectorWheel(true); + hideInputControls(); return true; } break; @@ -640,6 +642,7 @@ public class NumberPicker extends LinearLayout { mBeginEditOnUpEvent = false; onScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL); setDrawSelectorWheel(true); + hideInputControls(); return true; } break; diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java index 22f6f4ed93d8..d74ef245e5f7 100644 --- a/core/java/android/widget/TabWidget.java +++ b/core/java/android/widget/TabWidget.java @@ -174,8 +174,8 @@ public class TabWidget extends LinearLayout implements OnFocusChangeListener { void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) { // First, measure with no constraint final int unspecifiedWidth = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); - super.measureHorizontal(unspecifiedWidth, heightMeasureSpec); mImposedTabsHeight = -1; + super.measureHorizontal(unspecifiedWidth, heightMeasureSpec); int extraWidth = getMeasuredWidth() - MeasureSpec.getSize(widthMeasureSpec); if (extraWidth > 0) { diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 11e05e5d9c23..09c1ac5e916a 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -7091,6 +7091,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener // Only track when onStartTemporaryDetach() is called directly, // usually because this instance is an editable field in a list if (!mDispatchTemporaryDetach) mTemporaryDetach = true; + + // Because of View recycling in ListView, there is no easy way to know when a TextView with + // selection becomes visible again. Until a better solution is found, stop text selection + // mode (if any) as soon as this TextView is recycled. + stopSelectionActionMode(); } @Override @@ -7389,6 +7394,22 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return superResult; } + @Override + public boolean onGenericMotionEvent(MotionEvent event) { + if (mMovement != null && mText instanceof Spannable && mLayout != null) { + try { + if (mMovement.onGenericMotionEvent(this, (Spannable) mText, event)) { + return true; + } + } catch (AbstractMethodError ex) { + // onGenericMotionEvent was added to the MovementMethod interface in API 12. + // Ignore its absence in case third party applications implemented the + // interface directly. + } + } + return super.onGenericMotionEvent(event); + } + private void prepareCursorControllers() { boolean windowSupportsHandles = false; diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java index 841de062ddbf..fb2a72b8a4e1 100644 --- a/core/java/com/android/internal/app/ResolverActivity.java +++ b/core/java/com/android/internal/app/ResolverActivity.java @@ -68,7 +68,7 @@ public class ResolverActivity extends AlertActivity implements protected void onCreate(Bundle savedInstanceState, Intent intent, CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList, - boolean alwaysUseOption) { + boolean alwaysUseOption, boolean alwaysChoose) { super.onCreate(savedInstanceState); mPm = getPackageManager(); intent.setComponent(null); @@ -90,9 +90,10 @@ public class ResolverActivity extends AlertActivity implements mClearDefaultHint.setVisibility(View.GONE); } mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList); - if (mAdapter.getCount() > 1) { + int count = mAdapter.getCount(); + if (count > 1 || (count == 1 && alwaysChoose)) { ap.mAdapter = mAdapter; - } else if (mAdapter.getCount() == 1) { + } else if (count == 1) { startActivity(mAdapter.intentForPosition(0)); finish(); return; @@ -103,11 +104,22 @@ public class ResolverActivity extends AlertActivity implements setupAlert(); } + protected void onCreate(Bundle savedInstanceState, Intent intent, + CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList, + boolean alwaysUseOption) { + onCreate(savedInstanceState, intent, title, initialIntents, rList, alwaysUseOption, false); + } + public void onClick(DialogInterface dialog, int which) { ResolveInfo ri = mAdapter.resolveInfoForPosition(which); Intent intent = mAdapter.intentForPosition(which); + boolean alwaysCheck = (mAlwaysCheck != null && mAlwaysCheck.isChecked()); + onIntentSelected(ri, intent, alwaysCheck); + finish(); + } - if ((mAlwaysCheck != null) && mAlwaysCheck.isChecked()) { + protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) { + if (alwaysCheck) { // Build a reasonable intent filter, based on what matched. IntentFilter filter = new IntentFilter(); @@ -190,7 +202,6 @@ public class ResolverActivity extends AlertActivity implements if (intent != null) { startActivity(intent); } - finish(); } private final class DisplayResolveInfo { diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp index 7a53874c6983..7226e31ec39f 100644 --- a/core/jni/android_util_Binder.cpp +++ b/core/jni/android_util_Binder.cpp @@ -31,6 +31,8 @@ #include <binder/IPCThreadState.h> #include <utils/Log.h> #include <utils/SystemClock.h> +#include <utils/List.h> +#include <utils/KeyedVector.h> #include <cutils/logger.h> #include <binder/Parcel.h> #include <binder/ProcessState.h> @@ -322,25 +324,15 @@ private: class JavaBBinderHolder : public RefBase { public: - JavaBBinderHolder(JNIEnv* env, jobject object) - : mObject(object) - { - LOGV("Creating JavaBBinderHolder for Object %p\n", object); - } - ~JavaBBinderHolder() - { - LOGV("Destroying JavaBBinderHolder for Object %p\n", mObject); - } - - sp<JavaBBinder> get(JNIEnv* env) + sp<JavaBBinder> get(JNIEnv* env, jobject obj) { AutoMutex _l(mLock); sp<JavaBBinder> b = mBinder.promote(); if (b == NULL) { - b = new JavaBBinder(env, mObject); + b = new JavaBBinder(env, obj); mBinder = b; LOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n", - b.get(), b->getWeakRefs(), mObject, b->getWeakRefs()->getWeakCount()); + b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount()); } return b; @@ -354,20 +346,41 @@ public: private: Mutex mLock; - jobject mObject; wp<JavaBBinder> mBinder; }; // ---------------------------------------------------------------------------- +// Per-IBinder death recipient bookkeeping. This is how we reconcile local jobject +// death recipient references passed in through JNI with the permanent corresponding +// JavaDeathRecipient objects. + +class JavaDeathRecipient; + +class DeathRecipientList : public RefBase { + List< sp<JavaDeathRecipient> > mList; + Mutex mLock; + +public: + ~DeathRecipientList(); + + void add(const sp<JavaDeathRecipient>& recipient); + void remove(const sp<JavaDeathRecipient>& recipient); + sp<JavaDeathRecipient> find(jobject recipient); +}; + +// ---------------------------------------------------------------------------- + class JavaDeathRecipient : public IBinder::DeathRecipient { public: - JavaDeathRecipient(JNIEnv* env, jobject object) - : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), - mHoldsRef(true) + JavaDeathRecipient(JNIEnv* env, jobject object, sp<DeathRecipientList>& list) + : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object)), mList(list) { - incStrong(this); + // These objects manage their own lifetimes so are responsible for final bookkeeping. + // The list holds a strong reference to this object. + mList->add(this); + android_atomic_inc(&gNumDeathRefs); incRefsCreated(env); } @@ -391,16 +404,12 @@ public: void clearReference() { - bool release = false; - mLock.lock(); - if (mHoldsRef) { - mHoldsRef = false; - release = true; - } - mLock.unlock(); - if (release) { - decStrong(this); - } + mList->remove(this); + } + + bool matches(jobject obj) { + JNIEnv* env = javavm_to_jnienv(mVM); + return env->IsSameObject(obj, mObject); } protected: @@ -415,12 +424,57 @@ protected: private: JavaVM* const mVM; jobject const mObject; - Mutex mLock; - bool mHoldsRef; + sp<DeathRecipientList> mList; }; // ---------------------------------------------------------------------------- +DeathRecipientList::~DeathRecipientList() { + AutoMutex _l(mLock); + + // Should never happen -- the JavaDeathRecipient objects that have added themselves + // to the list are holding references on the list object. Only when they are torn + // down can the list header be destroyed. + if (mList.size() > 0) { + LOGE("Retiring binder %p with extant death recipients\n", this); + } +} + +void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) { + AutoMutex _l(mLock); + + mList.push_back(recipient); +} + +void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) { + AutoMutex _l(mLock); + + List< sp<JavaDeathRecipient> >::iterator iter; + for (iter = mList.begin(); iter != mList.end(); iter++) { + if (*iter == recipient) { + mList.erase(iter); + return; + } + } +} + +sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) { + AutoMutex _l(mLock); + + List< sp<JavaDeathRecipient> >::iterator iter; + for (iter = mList.begin(); iter != mList.end(); iter++) { + if ((*iter)->matches(recipient)) { + return *iter; + } + } + return NULL; +} + +static KeyedVector<IBinder*, sp<DeathRecipientList> > gDeathRecipientsByIBinder; +static Mutex gDeathRecipientMapLock; + +// ---------------------------------------------------------------------------- + namespace android { static void proxy_cleanup(const void* id, void* obj, void* cleanupCookie) @@ -490,7 +544,7 @@ sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj) if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) { JavaBBinderHolder* jbh = (JavaBBinderHolder*) env->GetIntField(obj, gBinderOffsets.mObject); - return jbh != NULL ? jbh->get(env) : NULL; + return jbh != NULL ? jbh->get(env, obj) : NULL; } if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) { @@ -621,26 +675,26 @@ static void android_os_Binder_flushPendingCommands(JNIEnv* env, jobject clazz) IPCThreadState::self()->flushCommands(); } -static void android_os_Binder_init(JNIEnv* env, jobject clazz) +static void android_os_Binder_init(JNIEnv* env, jobject obj) { - JavaBBinderHolder* jbh = new JavaBBinderHolder(env, clazz); + JavaBBinderHolder* jbh = new JavaBBinderHolder(); if (jbh == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return; } - LOGV("Java Binder %p: acquiring first ref on holder %p", clazz, jbh); - jbh->incStrong(clazz); - env->SetIntField(clazz, gBinderOffsets.mObject, (int)jbh); + LOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh); + jbh->incStrong((void*)android_os_Binder_init); + env->SetIntField(obj, gBinderOffsets.mObject, (int)jbh); } -static void android_os_Binder_destroy(JNIEnv* env, jobject clazz) +static void android_os_Binder_destroy(JNIEnv* env, jobject obj) { JavaBBinderHolder* jbh = (JavaBBinderHolder*) - env->GetIntField(clazz, gBinderOffsets.mObject); + env->GetIntField(obj, gBinderOffsets.mObject); if (jbh != NULL) { - env->SetIntField(clazz, gBinderOffsets.mObject, 0); - LOGV("Java Binder %p: removing ref on holder %p", clazz, jbh); - jbh->decStrong(clazz); + env->SetIntField(obj, gBinderOffsets.mObject, 0); + LOGV("Java Binder %p: removing ref on holder %p", obj, jbh); + jbh->decStrong((void*)android_os_Binder_init); } else { // Encountering an uninitialized binder is harmless. All it means is that // the Binder was only partially initialized when its finalizer ran and called @@ -648,7 +702,7 @@ static void android_os_Binder_destroy(JNIEnv* env, jobject clazz) // For example, a Binder subclass constructor might have thrown an exception before // it could delegate to its superclass's constructor. Consequently init() would // not have been called and the holder pointer would remain NULL. - LOGV("Java Binder %p: ignoring uninitialized binder", clazz); + LOGV("Java Binder %p: ignoring uninitialized binder", obj); } } @@ -973,8 +1027,25 @@ static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj, LOGV("linkToDeath: binder=%p recipient=%p\n", target, recipient); if (!target->localBinder()) { - sp<JavaDeathRecipient> jdr = new JavaDeathRecipient(env, recipient); - status_t err = target->linkToDeath(jdr, recipient, flags); + sp<JavaDeathRecipient> jdr; + + { + sp<DeathRecipientList> list; + AutoMutex _maplocker(gDeathRecipientMapLock); + + ssize_t listIndex = gDeathRecipientsByIBinder.indexOfKey(target); + if (listIndex < 0) { + // Set up the death notice bookkeeping for this binder lazily + list = new DeathRecipientList; + gDeathRecipientsByIBinder.add(target, list); + } else { + list = gDeathRecipientsByIBinder.valueAt(listIndex); + } + + jdr = new JavaDeathRecipient(env, recipient, list); + } + + status_t err = target->linkToDeath(jdr, NULL, flags); if (err != NO_ERROR) { // Failure adding the death recipient, so clear its reference // now. @@ -1003,15 +1074,33 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj, LOGV("unlinkToDeath: binder=%p recipient=%p\n", target, recipient); if (!target->localBinder()) { - wp<IBinder::DeathRecipient> dr; - status_t err = target->unlinkToDeath(NULL, recipient, flags, &dr); - if (err == NO_ERROR && dr != NULL) { - sp<IBinder::DeathRecipient> sdr = dr.promote(); - JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); - if (jdr != NULL) { - jdr->clearReference(); + status_t err = NAME_NOT_FOUND; + sp<JavaDeathRecipient> origJDR; + { + AutoMutex _maplocker(gDeathRecipientMapLock); + ssize_t listIndex = gDeathRecipientsByIBinder.indexOfKey(target); + if (listIndex >= 0) { + sp<DeathRecipientList> list = gDeathRecipientsByIBinder.valueAt(listIndex); + origJDR = list->find(recipient); + } else { + // If there is no DeathRecipientList for this binder, it means the binder + // is dead and in the process of being cleaned up. + err = DEAD_OBJECT; + } + } + // If we found the matching recipient, proceed to unlink using that + if (origJDR != NULL) { + wp<IBinder::DeathRecipient> dr; + err = target->unlinkToDeath(origJDR, NULL, flags, &dr); + if (err == NO_ERROR && dr != NULL) { + sp<IBinder::DeathRecipient> sdr = dr.promote(); + JavaDeathRecipient* jdr = static_cast<JavaDeathRecipient*>(sdr.get()); + if (jdr != NULL) { + jdr->clearReference(); + } } } + if (err == NO_ERROR || err == DEAD_OBJECT) { res = JNI_TRUE; } else { @@ -1031,6 +1120,15 @@ static void android_os_BinderProxy_destroy(JNIEnv* env, jobject obj) env->SetIntField(obj, gBinderProxyOffsets.mObject, 0); b->decStrong(obj); IPCThreadState::self()->flushCommands(); + + // tear down the death recipient bookkeeping + { + AutoMutex _maplocker(gDeathRecipientMapLock); + ssize_t listIndex = gDeathRecipientsByIBinder.indexOfKey(b); + if (listIndex >= 0) { + gDeathRecipientsByIBinder.removeItemsAt((size_t)listIndex); + } + } } // ---------------------------------------------------------------------------- @@ -1152,15 +1250,13 @@ static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz, if (parcel == NULL) { return; } - void *dest; const status_t err = parcel->writeInt32(length); if (err != NO_ERROR) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); } - dest = parcel->writeInplace(length); - + void* dest = parcel->writeInplace(length); if (dest == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return; @@ -1168,7 +1264,7 @@ static void android_os_Parcel_writeNative(JNIEnv* env, jobject clazz, jbyte* ar = (jbyte*)env->GetPrimitiveArrayCritical((jarray)data, 0); if (ar) { - memcpy(dest, ar, length); + memcpy(dest, ar + offset, length); env->ReleasePrimitiveArrayCritical((jarray)data, ar, 0); } } diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp index ac8835a60be7..160d654b658f 100644 --- a/core/jni/android_view_Display.cpp +++ b/core/jni/android_view_Display.cpp @@ -44,6 +44,8 @@ struct offsets_t { }; static offsets_t offsets; +static int gShortSize = -1; +static int gLongSize = -1; static int gOldSize = -1; static int gNewSize = -1; @@ -76,6 +78,10 @@ static jint android_view_Display_getWidth( { DisplayID dpy = env->GetIntField(clazz, offsets.display); jint w = SurfaceComposerClient::getDisplayWidth(dpy); + if (gShortSize > 0) { + jint h = SurfaceComposerClient::getDisplayHeight(dpy); + return w < h ? gShortSize : gLongSize; + } return w == gOldSize ? gNewSize : w; } @@ -84,9 +90,27 @@ static jint android_view_Display_getHeight( { DisplayID dpy = env->GetIntField(clazz, offsets.display); int h = SurfaceComposerClient::getDisplayHeight(dpy); + if (gShortSize > 0) { + jint w = SurfaceComposerClient::getDisplayWidth(dpy); + return h < w ? gShortSize : gLongSize; + } return h == gOldSize ? gNewSize : h; } +static jint android_view_Display_getRealWidth( + JNIEnv* env, jobject clazz) +{ + DisplayID dpy = env->GetIntField(clazz, offsets.display); + return SurfaceComposerClient::getDisplayWidth(dpy); +} + +static jint android_view_Display_getRealHeight( + JNIEnv* env, jobject clazz) +{ + DisplayID dpy = env->GetIntField(clazz, offsets.display); + return SurfaceComposerClient::getDisplayHeight(dpy); +} + static jint android_view_Display_getOrientation( JNIEnv* env, jobject clazz) { @@ -100,13 +124,6 @@ static jint android_view_Display_getDisplayCount( return SurfaceComposerClient::getNumberOfDisplays(); } -static jint android_view_Display_unmapDisplaySize( - JNIEnv* env, jclass clazz, jint newSize) -{ - if (newSize == gNewSize) return gOldSize; - return newSize; -} - // ---------------------------------------------------------------------------- const char* const kClassPathName = "android/view/Display"; @@ -124,10 +141,12 @@ static JNINativeMethod gMethods[] = { (void*)android_view_Display_getWidth }, { "getHeight", "()I", (void*)android_view_Display_getHeight }, + { "getRealWidth", "()I", + (void*)android_view_Display_getRealWidth }, + { "getRealHeight", "()I", + (void*)android_view_Display_getRealHeight }, { "getOrientation", "()I", - (void*)android_view_Display_getOrientation }, - { "unmapDisplaySize", "(I)I", - (void*)android_view_Display_unmapDisplaySize } + (void*)android_view_Display_getOrientation } }; void nativeClassInit(JNIEnv* env, jclass clazz) @@ -146,7 +165,15 @@ int register_android_view_Display(JNIEnv* env) int len = property_get("persist.demo.screensizehack", buf, ""); if (len > 0) { int temp1, temp2; - if (sscanf(buf, "%d=%d", &temp1, &temp2) == 2) { + if (sscanf(buf, "%dx%d", &temp1, &temp2) == 2) { + if (temp1 < temp2) { + gShortSize = temp1; + gLongSize = temp2; + } else { + gShortSize = temp2; + gLongSize = temp1; + } + } else if (sscanf(buf, "%d=%d", &temp1, &temp2) == 2) { gOldSize = temp1; gNewSize = temp2; } @@ -157,4 +184,3 @@ int register_android_view_Display(JNIEnv* env) } }; - diff --git a/core/jni/android_view_InputChannel.cpp b/core/jni/android_view_InputChannel.cpp index 4a4393ae2dd1..0c2801cab7ba 100644 --- a/core/jni/android_view_InputChannel.cpp +++ b/core/jni/android_view_InputChannel.cpp @@ -186,9 +186,21 @@ static void android_view_InputChannel_nativeReadFromParcel(JNIEnv* env, jobject bool isInitialized = parcel->readInt32(); if (isInitialized) { String8 name = parcel->readString8(); - int32_t ashmemFd = dup(parcel->readFileDescriptor()); - int32_t receivePipeFd = dup(parcel->readFileDescriptor()); - int32_t sendPipeFd = dup(parcel->readFileDescriptor()); + int32_t parcelAshmemFd = parcel->readFileDescriptor(); + int32_t ashmemFd = dup(parcelAshmemFd); + if (ashmemFd < 0) { + LOGE("Error %d dup ashmem fd %d.", errno, parcelAshmemFd); + } + int32_t parcelReceivePipeFd = parcel->readFileDescriptor(); + int32_t receivePipeFd = dup(parcelReceivePipeFd); + if (receivePipeFd < 0) { + LOGE("Error %d dup receive pipe fd %d.", errno, parcelReceivePipeFd); + } + int32_t parcelSendPipeFd = parcel->readFileDescriptor(); + int32_t sendPipeFd = dup(parcelSendPipeFd); + if (sendPipeFd < 0) { + LOGE("Error %d dup send pipe fd %d.", errno, parcelSendPipeFd); + } if (ashmemFd < 0 || receivePipeFd < 0 || sendPipeFd < 0) { if (ashmemFd >= 0) ::close(ashmemFd); if (receivePipeFd >= 0) ::close(receivePipeFd); diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index be66e9c4d5e9..bd2e6694f3f5 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -177,7 +177,7 @@ static sp<Surface> getSurface(JNIEnv* env, jobject clazz) sp<ANativeWindow> android_Surface_getNativeWindow( JNIEnv* env, jobject clazz) { - return getSurface(env, clazz).get(); + return getSurface(env, clazz); } static void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface) diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index beb824ca18b7..50d3fb8204d2 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -466,12 +466,13 @@ android:label="@string/permlab_flashlight" android:description="@string/permdesc_flashlight" /> - <!-- Allows an application to access USB devices --> - <permission android:name="android.permission.ACCESS_USB" + <!-- Allows an application to manage preferences and permissions for USB devices + @hide --> + <permission android:name="android.permission.MANAGE_USB" android:permissionGroup="android.permission-group.HARDWARE_CONTROLS" - android:protectionLevel="normal" - android:label="@string/permlab_accessUsb" - android:description="@string/permdesc_accessUsb" /> + android:protectionLevel="signatureOrSystem" + android:label="@string/permlab_manageUsb" + android:description="@string/permdesc_manageUsb" /> <!-- Allows an application to access the MTP USB kernel driver. For use only by the device side MTP implementation. @@ -1372,11 +1373,18 @@ <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> + <activity android:name="com.android.internal.app.NetInitiatedActivity" android:theme="@style/Theme.Holo.Dialog.Alert" android:excludeFromRecents="true"> </activity> + <activity android:name="com.android.server.usb.UsbResolverActivity" + android:theme="@style/Theme.Holo.Dialog.Alert" + android:finishOnCloseSystemDialogs="true" + android:excludeFromRecents="true"> + </activity> + <service android:name="com.android.server.LoadAverageService" android:exported="true" /> diff --git a/libs/rs/java/HelloWorld/AndroidManifest.xml b/core/res/res/layout/webview_select_singlechoice.xml index e7c9a95051c9..c0753a8935db 100644 --- a/libs/rs/java/HelloWorld/AndroidManifest.xml +++ b/core/res/res/layout/webview_select_singlechoice.xml @@ -4,9 +4,9 @@ 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. @@ -14,18 +14,17 @@ limitations under the License. --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.rs.helloworld"> - <uses-sdk android:minSdkVersion="11" /> - <application android:label="HelloWorld" - android:icon="@drawable/test_pattern"> - <activity android:name="HelloWorld" - android:label="HelloWorld" - android:theme="@android:style/Theme.Black.NoTitleBar"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> +<TextView xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@android:id/text1" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="?android:attr/listPreferredItemHeight" + android:textAppearance="?android:attr/textAppearanceLarge" + android:textColor="?android:attr/textColorAlertDialogListItem" + android:gravity="center_vertical" + android:paddingLeft="12dip" + android:paddingRight="7dip" + android:ellipsize="marquee" + style="?android:attr/spinnerDropDownItemStyle" + android:background="?android:attr/activatedBackgroundIndicator" +/> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index cb44a3af3159..c8157586df7f 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -296,9 +296,6 @@ <!-- Indicate whether the SD card is accessible without removing the battery. --> <bool name="config_batterySdCardAccessibility">false</bool> - <!-- Indicate whether the device has USB host support. --> - <bool name="config_hasUsbHostSupport">false</bool> - <!-- List of file paths for USB host busses to exclude from USB host support. For example, if the first USB bus on the device is used to communicate with the modem or some other restricted hardware, add "/dev/bus/usb/001/" diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 361bb6c58e3a..8ef9a3b247b4 100755 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1031,9 +1031,9 @@ the flashlight.</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_accessUsb">access USB devices</string> + <string name="permlab_manageUsb">manage preferences and permissions for USB devices</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> - <string name="permdesc_accessUsb">Allows the application to access USB devices.</string> + <string name="permdesc_manageUsb">Allows the application to manage preferences and permissions for USB devices.</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_accessMtp">implement MTP protocol</string> @@ -1869,6 +1869,115 @@ e.g. (John Smith)(, )(123 Main Street) --> <string name="autofill_address_summary_format">$1$2$3</string> + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_attention_ignored_re">attention|attn</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_region_ignored_re">province|region|other<!-- es -->|provincia<!-- pt-BR, pt-PT -->|bairro|suburb</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_company_re">company|business|organization|organisation|department<!-- de-DE -->|firma|firmenname<!-- es -->|empresa<!-- fr-FR -->|societe|société<!-- it-IT -->|ragione.?sociale<!-- ja-JP -->|会社<!-- ru -->|название.?компании<!-- zh-CN -->|单位|公司</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_address_line_1_re">address.?line|address1|addr1|street<!-- de-DE -->|strasse|straße|hausnummer|housenumber<!-- en-GB -->|house.?name<!-- es -->|direccion|dirección<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所1<!-- pt-BR, pt-PT -->|morada|endereço<!-- ru -->|Адрес<!-- zh-CN -->|地址</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_address_line_1_label_re">address<!-- fr-FR -->|adresse<!-- it-IT -->|indirizzo<!-- ja-JP -->|住所<!-- zh-CN -->|地址</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_address_line_2_re">address.?line2|address2|addr2|street|suite|unit<!-- de-DE -->|adresszusatz|ergänzende.?angaben<!-- es -->|direccion2|colonia|adicional<!-- fr-FR -->|addresssuppl|complementnom|appartement<!-- it-IT -->|indirizzo2<!-- ja-JP -->|住所2</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_address_line_3_re">address.?line3|address3|addr3|street|line3<!-- es -->|municipio<!-- fr-FR -->|batiment|residence<!-- it-IT -->|indirizzo3</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_country_re">country|location<!-- ja-JP -->|国<!-- zh-CN -->|国家</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_zip_code_re">zip|postal|post code|pcode|^1z$<!-- de-DE -->|postleitzahl<!-- es -->|cp<!-- fr-FR -->|cdp<!-- it-IT -->|cap<!-- ja-JP -->|郵便番号<!-- pt-BR, pt-PT -->|codigo|codpos|cep<!-- ru -->|Почтовый.?Индекс<!--zh-CN -->|邮政编码|邮编<!-- zh-TW -->|郵遞區號</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_zip_4_re">zip|^-$|post2<!-- pt-BR, pt-PT -->|codpos2</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_city_re">city|town<!-- de-DE -->|ort|stadt<!-- en-AU -->|suburb<!-- es -->|ciudad|provincia|localidad|poblacion<!-- fr-FR -->|ville|commune<!-- it-IT -->|localita<!-- ja-JP -->|市区町村<!-- pt-BR, pt-PT -->|cidade<!-- ru -->|Город<!-- zh-CN -->|市<!-- zh-TW -->|分區</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_state_re">state|county|region|province<!-- de-DE -->|land<!-- en-UK -->|county|principality<!-- ja-JP -->|都道府県<!-- pt-BR, pt-PT -->|estado|provincia<!-- ru -->|область<!-- zh-CN -->|省<!-- zh-TW -->|地區</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_address_type_same_as_re">same as</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_address_type_use_my_re">use my</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_billing_designator_re">bill</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_shipping_designator_re">ship</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_email_re">e.?mail<!-- ja-JP -->|メールアドレス<!-- ru -->|Электронной.?Почты<!-- zh-CN -->|邮件|邮箱<!-- zh-TW -->|電郵地址</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_username_re">user.?name|user.?id<!-- de-DE -->|vollständiger.?name<!-- zh-CN -->|用户名</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_name_re">^name|full.?name|your.?name|customer.?name|firstandlastname<!-- es -->|nombre.*y.*apellidos<!-- fr-FR -->|^nom<!-- ja-JP -->|お名前|氏名<!-- pt-BR, pt-PT -->|^nome<!-- zh-CN -->|姓名</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_name_specific_re">^name<!-- fr-FR -->|^nom<!-- pt-BR, pt-PT -->|^nome</string> + + <!-- Do not translate. Regex used by AutoFill. --> + + <string name="autofill_first_name_re">irst.*name|initials|fname|first$<!-- de-DE -->|vorname<!-- es -->|nombre<!-- fr-FR -->|forename|prénom|prenom<!-- ja-JP -->|名<!-- pt-BR, pt-PT -->|nome<!-- ru -->|Имя</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_middle_initial_re">middle.*initial|m\\.i\\.|mi$</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_middle_name_re">middle.*name|mname|middle$<!-- es -->|apellido.?materno|lastlastname</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_last_name_re">last.*name|lname|surname|last$<!-- de-DE -->|nachname<!-- es -->|apellidos<!-- fr-FR -->|famille|^nom<!-- it-IT -->|cognome<!-- ja-JP -->|姓<!-- pt-BR, pt-PT -->|morada|apelidos|surename|sobrenome<!-- ru -->|Фамилия</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_phone_re">phone<!-- de-DE -->|telefonnummer<!-- es -->|telefono|teléfono<!-- fr-FR -->|telfixe<!-- ja-JP -->|電話<!-- pt-BR, pt-PT -->|telefone|telemovel<!-- ru -->|телефон<!-- zh-CN -->|电话</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_area_code_re">area code</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_phone_prefix_re">^-$|\\)$|prefix<!-- fr-FR -->|preselection<!-- pt-BR, pt-PT -->|ddd</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_phone_suffix_re">^-$|suffix</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_phone_extension_re">ext<!-- pt-BR, pt-PT -->|ramal</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_name_on_card_re">card.?holder|name.?on.?card|ccname|owner<!-- de-DE -->|karteninhaber<!-- es -->|nombre.*tarjeta<!-- fr-FR -->|nom.*carte<!-- it-IT -->|nome.*cart<!-- ja-JP -->|名前<!-- ru -->|Имя.*карты<!-- zh-CN -->|信用卡开户名|开户名|持卡人姓名<!-- zh-TW -->|持卡人姓名</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_name_on_card_contextual_re">name</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_card_cvc_re">verification|card identification|cvn|security code|cvv code|cvc</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_card_number_re">number|card.?#|card.?no|ccnum<!-- de-DE -->|nummer<!-- es -->|credito|numero|número<!-- fr-FR -->|numéro<!-- ja-JP -->|カード番号<!-- ru -->|Номер.*карты<!-- zh-CN -->|信用卡号|信用卡号码<!-- zh-TW -->|信用卡卡號</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_expiration_month_re">expir|exp.*month|exp.*date|ccmonth<!-- de-DE -->|gueltig|gültig|monat<!-- es -->|fecha<!-- fr-FR -->|date.*exp<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|月</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_expiration_date_re">exp|^/|year<!-- de-DE -->|ablaufdatum|gueltig|gültig|yahr<!-- es -->|fecha<!-- it-IT -->|scadenza<!-- ja-JP -->|有効期限<!-- pt-BR, pt-PT -->|validade<!-- ru -->|Срок действия карты<!-- zh-CN -->|年|有效期</string> + + <!-- Do not translate. Regex used by AutoFill. --> + <string name="autofill_card_ignored_re">^card</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_readHistoryBookmarks">read Browser\'s history and bookmarks</string> @@ -2193,6 +2302,8 @@ <string name="clearDefaultHintMsg">Clear default in Home Settings > Applications > Manage applications.</string> <!-- Default title for the activity chooser, when one is not given. Android allows multiple activities to perform an action. for example, there may be many ringtone pickers installed. A dialog is shown to the user allowing him to pick which activity should be used. This is the title. --> <string name="chooseActivity">Select an action</string> + <!-- title for the USB activity chooser. --> + <string name="chooseUsbActivity">Select an application for the USB device</string> <!-- Text to display when there are no activities found to display in the activity chooser. See the "Select an action" title. --> <string name="noApplications">No applications can perform this action.</string> diff --git a/libs/rs/java/HelloCompute/AndroidManifest.xml b/data/etc/android.hardware.usb.accessory.xml index 8c7ac2f71c76..29df966b7065 100644 --- a/libs/rs/java/HelloCompute/AndroidManifest.xml +++ b/data/etc/android.hardware.usb.accessory.xml @@ -4,9 +4,9 @@ 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. @@ -14,17 +14,7 @@ limitations under the License. --> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.example.hellocompute"> - - <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-sdk android:minSdkVersion="11" /> - <application android:label="HelloCompute"> - <activity android:name="HelloCompute"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> +<!-- This is the standard feature indicating that the device supports USB accessories. --> +<permissions> + <feature name="android.hardware.usb.accessory" /> +</permissions> diff --git a/data/etc/android.hardware.usb.host.xml b/data/etc/android.hardware.usb.host.xml new file mode 100644 index 000000000000..b0ca82c98028 --- /dev/null +++ b/data/etc/android.hardware.usb.host.xml @@ -0,0 +1,21 @@ +<?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. +--> + +<!-- This is the standard feature indicating that the device can communicate + with USB devices as the USB host. --> +<permissions> + <feature name="android.hardware.usb.host" /> +</permissions> diff --git a/libs/rs/java/HelloCompute/res/layout/main.xml b/data/etc/com.google.android.usb.xml index 3f7de4313a62..fae3d2380dd0 100644 --- a/libs/rs/java/HelloCompute/res/layout/main.xml +++ b/data/etc/com.google.android.usb.xml @@ -14,18 +14,7 @@ limitations under the License. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent"> - - <ImageView - android:id="@+id/displayin" - android:layout_width="320dip" - android:layout_height="266dip" /> - - <ImageView - android:id="@+id/displayout" - android:layout_width="320dip" - android:layout_height="266dip" /> - -</LinearLayout> +<permissions> + <library name="com.google.android.usb" + file="/system/framework/com.google.android.usb.jar" /> +</permissions> diff --git a/docs/html/index.jd b/docs/html/index.jd index 2248752adda0..f1bb59f66086 100644 --- a/docs/html/index.jd +++ b/docs/html/index.jd @@ -11,14 +11,10 @@ home=true </div><!-- end homeTitle --> <div id="announcement-block"> <!-- total max width is 520px --> - <img src="{@docRoot}images/home/market-intl.png" alt="Android -Market" width="104" height="120" style="padding:10px 60px 5px" /> - <div id="announcement" style="width:295px"> -<p>We're pleased to announce that paid apps are available in more locations of the world! Developers -from 20 more locations can now sell paid apps on Android Market. Users in more locations will also -soon be able to purchase apps.</p><p><a -href="http://android-developers.blogspot.com/2010/09/more-countries-more-sellers-more-buyers.html"> -Learn more »</a></p> + <img src="{@docRoot}assets/images/home/GDC2011.png" alt="Android at GDC 2011" width="203px" style="padding-left:22px;padding-bottom:28px;padding-top:22px;"/> + <div id="announcement" style="width:275px"> + <p>Android will be at the <a href="http://www.gdconf.com/">2011 Game Developers Conference</a> in San Francisco, from March 1st to 4th. We're looking forward to seeing you there!</p> + <p><a href="http://android-developers.blogspot.com/2011/02/heading-for-gdc.html">Learn more »</a></p> </div> <!-- end annoucement --> </div> <!-- end annoucement-block --> </div><!-- end topAnnouncement --> diff --git a/docs/html/resources/resources-data.js b/docs/html/resources/resources-data.js index e919de94ee0a..14118bbcd5fa 100644 --- a/docs/html/resources/resources-data.js +++ b/docs/html/resources/resources-data.js @@ -497,12 +497,12 @@ var ANDROID_RESOURCES = [ }, { tags: ['sample', 'new', 'newfeature', 'performance', 'gamedev', 'gl'], - path: 'samples/Renderscript/index.html', + path: 'samples/RenderScript/index.html', title: { - en: 'Renderscript' + en: 'RenderScript' }, description: { - en: 'A set of samples that demonstrate how to use various features of the Renderscript APIs.' + en: 'A set of samples that demonstrate how to use various features of the RenderScript APIs.' } }, { diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java index 4fc419c6a53a..fae22f004a58 100644 --- a/graphics/java/android/renderscript/Element.java +++ b/graphics/java/android/renderscript/Element.java @@ -21,7 +21,7 @@ import android.util.Log; /** * <p>The most basic data type. An element represents one cell of a memory allocation. - * Element is the basic data type of Renderscript. An element can be of two forms: Basic elements or Complex forms. + * Element is the basic data type of Renderscript. An element can be of two forms: Basic elements or Complex forms. * Examples of basic elements are:</p> * <ul> * <li>Single float value</li> @@ -29,7 +29,7 @@ import android.util.Log; * <li>single RGB-565 color</li> * <li>single unsigned int 16</li> * </ul> - * <p>Complex elements contain a list of sub-elements and names that + * <p>Complex elements contain a list of sub-elements and names that * represents a structure of data. The fields can be accessed by name * from a script or shader. The memory layout is defined and ordered. Data * alignment is determinied by the most basic primitive type. i.e. a float4 @@ -403,7 +403,7 @@ public class Element extends BaseObj { if(rs.mElement_MATRIX_3X3 == null) { rs.mElement_MATRIX_3X3 = createUser(rs, DataType.MATRIX_3X3); } - return rs.mElement_MATRIX_4X4; + return rs.mElement_MATRIX_3X3; } public static Element MATRIX_2X2(RenderScript rs) { diff --git a/include/binder/IBinder.h b/include/binder/IBinder.h index 749a977b83b5..81b56c2b2b3b 100644 --- a/include/binder/IBinder.h +++ b/include/binder/IBinder.h @@ -98,7 +98,7 @@ public: * Register the @a recipient for a notification if this binder * goes away. If this binder object unexpectedly goes away * (typically because its hosting process has been killed), - * then DeathRecipient::binderDied() will be called with a referene + * then DeathRecipient::binderDied() will be called with a reference * to this. * * The @a cookie is optional -- if non-NULL, it should be a diff --git a/include/utils/StrongPointer.h b/include/utils/StrongPointer.h index a8c989749b60..49fa3a8d6f62 100644 --- a/include/utils/StrongPointer.h +++ b/include/utils/StrongPointer.h @@ -133,7 +133,7 @@ sp<T>::sp(const sp<T>& other) template<typename T> template<typename U> sp<T>::sp(U* other) : m_ptr(other) { - if (other) other->incStrong(this); + if (other) ((T*)other)->incStrong(this); } template<typename T> template<typename U> @@ -170,7 +170,7 @@ sp<T>& sp<T>::operator = (T* other) template<typename T> template<typename U> sp<T>& sp<T>::operator = (const sp<U>& other) { - U* otherPtr(other.m_ptr); + T* otherPtr(other.m_ptr); if (otherPtr) otherPtr->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = otherPtr; @@ -180,7 +180,7 @@ sp<T>& sp<T>::operator = (const sp<U>& other) template<typename T> template<typename U> sp<T>& sp<T>::operator = (U* other) { - if (other) other->incStrong(this); + if (other) ((T*)other)->incStrong(this); if (m_ptr) m_ptr->decStrong(this); m_ptr = other; return *this; diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk index 25c8beb3b2f5..5ab4804b69e3 100644 --- a/libs/rs/Android.mk +++ b/libs/rs/Android.mk @@ -152,9 +152,4 @@ LOCAL_MODULE_TAGS := optional include $(BUILD_HOST_STATIC_LIBRARY) -# include the java examples -include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk,\ - java \ - )) - endif #simulator diff --git a/libs/rs/java/Android.mk b/libs/rs/java/Android.mk deleted file mode 100644 index 5053e7d64389..000000000000 --- a/libs/rs/java/Android.mk +++ /dev/null @@ -1 +0,0 @@ -include $(call all-subdir-makefiles) diff --git a/libs/rs/java/Balls/AndroidManifest.xml b/libs/rs/java/Balls/AndroidManifest.xml deleted file mode 100644 index f3384ece05ee..000000000000 --- a/libs/rs/java/Balls/AndroidManifest.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.balls"> - <uses-sdk android:minSdkVersion="11" /> - <application - android:label="Balls" - android:icon="@drawable/test_pattern"> - <activity android:name="Balls" - android:screenOrientation="landscape"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/libs/rs/java/Balls/_index.html b/libs/rs/java/Balls/_index.html deleted file mode 100644 index 87604854d3d1..000000000000 --- a/libs/rs/java/Balls/_index.html +++ /dev/null @@ -1 +0,0 @@ -<p>A brute force physics simulation that renders many balls onto the screen and moves them according to user touch and gravity.</p>
\ No newline at end of file diff --git a/libs/rs/java/Balls/res/drawable/flares.png b/libs/rs/java/Balls/res/drawable/flares.png Binary files differdeleted file mode 100644 index 3a5c970fc2b9..000000000000 --- a/libs/rs/java/Balls/res/drawable/flares.png +++ /dev/null diff --git a/libs/rs/java/Balls/res/drawable/test_pattern.png b/libs/rs/java/Balls/res/drawable/test_pattern.png Binary files differdeleted file mode 100644 index e7d145554c00..000000000000 --- a/libs/rs/java/Balls/res/drawable/test_pattern.png +++ /dev/null diff --git a/libs/rs/java/Balls/src/com/android/balls/Balls.java b/libs/rs/java/Balls/src/com/android/balls/Balls.java deleted file mode 100644 index c24e616cd44d..000000000000 --- a/libs/rs/java/Balls/src/com/android/balls/Balls.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.balls; - -import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScript; - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.provider.Settings.System; -import android.util.Config; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.Button; -import android.widget.ListView; - -import java.lang.Runtime; - -import android.app.Activity; -import android.content.Context; -import android.os.Bundle; -import android.view.View; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; - -public class Balls extends Activity implements SensorEventListener { - //EventListener mListener = new EventListener(); - - private static final String LOG_TAG = "libRS_jni"; - private static final boolean DEBUG = false; - private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; - - private BallsView mView; - private SensorManager mSensorManager; - - // get the current looper (from your Activity UI thread for instance - - - public void onSensorChanged(SensorEvent event) { - //android.util.Log.d("rs", "sensor: " + event.sensor + ", x: " + event.values[0] + ", y: " + event.values[1] + ", z: " + event.values[2]); - synchronized (this) { - if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { - if(mView != null) { - mView.setAccel(event.values[0], event.values[1], event.values[2]); - } - } - } - } - - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); - - // Create our Preview view and set it as the content of our - // Activity - mView = new BallsView(this); - setContentView(mView); - } - - @Override - protected void onResume() { - mSensorManager.registerListener(this, - mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), - SensorManager.SENSOR_DELAY_FASTEST); - - // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity looses focus - super.onResume(); - mView.resume(); - } - - @Override - protected void onPause() { - super.onPause(); - mView.pause(); - Runtime.getRuntime().exit(0); - } - - @Override - protected void onStop() { - mSensorManager.unregisterListener(this); - super.onStop(); - } - - static void log(String message) { - if (LOG_ENABLED) { - Log.v(LOG_TAG, message); - } - } - - -} - diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java b/libs/rs/java/Balls/src/com/android/balls/BallsRS.java deleted file mode 100644 index 50ee9212ae0f..000000000000 --- a/libs/rs/java/Balls/src/com/android/balls/BallsRS.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.balls; - -import android.content.res.Resources; -import android.renderscript.*; -import android.util.Log; - -public class BallsRS { - public static final int PART_COUNT = 900; - - public BallsRS() { - } - - private Resources mRes; - private RenderScriptGL mRS; - private ScriptC_balls mScript; - private ScriptC_ball_physics mPhysicsScript; - private ProgramFragment mPFLines; - private ProgramFragment mPFPoints; - private ProgramVertex mPV; - private ScriptField_Point mPoints; - private ScriptField_VpConsts mVpConsts; - - void updateProjectionMatrices() { - mVpConsts = new ScriptField_VpConsts(mRS, 1, - Allocation.USAGE_SCRIPT | - Allocation.USAGE_GRAPHICS_CONSTANTS); - ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item(); - Matrix4f mvp = new Matrix4f(); - mvp.loadOrtho(0, mRS.getWidth(), mRS.getHeight(), 0, -1, 1); - i.MVP = mvp; - mVpConsts.set(i, 0, true); - } - - private void createProgramVertex() { - updateProjectionMatrices(); - - ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS); - String t = "varying vec4 varColor;\n" + - "void main() {\n" + - " vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" + - " pos.xy = ATTRIB_position;\n" + - " gl_Position = UNI_MVP * pos;\n" + - " varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" + - " gl_PointSize = ATTRIB_size;\n" + - "}\n"; - sb.setShader(t); - sb.addConstant(mVpConsts.getType()); - sb.addInput(mPoints.getElement()); - ProgramVertex pvs = sb.create(); - pvs.bindConstants(mVpConsts.getAllocation(), 0); - mRS.bindProgramVertex(pvs); - } - - private Allocation loadTexture(int id) { - final Allocation allocation = - Allocation.createFromBitmapResource(mRS, mRes, - id, Allocation.MipmapControl.MIPMAP_NONE, - Allocation.USAGE_GRAPHICS_TEXTURE); - return allocation; - } - - ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) { - ProgramStore.Builder builder = new ProgramStore.Builder(rs); - builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); - builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE); - builder.setDitherEnabled(false); - builder.setDepthMaskEnabled(false); - return builder.create(); - } - - public void init(RenderScriptGL rs, Resources res, int width, int height) { - mRS = rs; - mRes = res; - - ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs); - pfb.setPointSpriteTexCoordinateReplacement(true); - pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE, - ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); - pfb.setVaryingColor(true); - mPFPoints = pfb.create(); - - pfb = new ProgramFragmentFixedFunction.Builder(rs); - pfb.setVaryingColor(true); - mPFLines = pfb.create(); - - android.util.Log.e("rs", "Load texture"); - mPFPoints.bindTexture(loadTexture(R.drawable.flares), 0); - - mPoints = new ScriptField_Point(mRS, PART_COUNT, Allocation.USAGE_SCRIPT); - - Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS); - smb.addVertexAllocation(mPoints.getAllocation()); - smb.addIndexSetType(Mesh.Primitive.POINT); - Mesh smP = smb.create(); - - mPhysicsScript = new ScriptC_ball_physics(mRS, mRes, R.raw.ball_physics); - - mScript = new ScriptC_balls(mRS, mRes, R.raw.balls); - mScript.set_partMesh(smP); - mScript.set_physics_script(mPhysicsScript); - mScript.bind_point(mPoints); - mScript.bind_balls1(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT)); - mScript.bind_balls2(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT)); - - mScript.set_gPFLines(mPFLines); - mScript.set_gPFPoints(mPFPoints); - createProgramVertex(); - - mRS.bindProgramStore(BLEND_ADD_DEPTH_NONE(mRS)); - - mPhysicsScript.set_gMinPos(new Float2(5, 5)); - mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5)); - - mScript.invoke_initParts(width, height); - - mRS.bindRootScript(mScript); - } - - public void newTouchPosition(float x, float y, float pressure, int id) { - mPhysicsScript.invoke_touch(x, y, pressure, id); - } - - public void setAccel(float x, float y) { - mPhysicsScript.set_gGravityVector(new Float2(x, y)); - } - -} diff --git a/libs/rs/java/Balls/src/com/android/balls/BallsView.java b/libs/rs/java/Balls/src/com/android/balls/BallsView.java deleted file mode 100644 index 4442eec9ec8d..000000000000 --- a/libs/rs/java/Balls/src/com/android/balls/BallsView.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.balls; - -import java.io.Writer; -import java.util.ArrayList; -import java.util.concurrent.Semaphore; - -import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScript; -import android.renderscript.RenderScriptGL; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.KeyEvent; -import android.view.MotionEvent; - -public class BallsView extends RSSurfaceView { - - public BallsView(Context context) { - super(context); - //setFocusable(true); - } - - private RenderScriptGL mRS; - private BallsRS mRender; - - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - super.surfaceChanged(holder, format, w, h); - if (mRS == null) { - RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); - mRS = createRenderScriptGL(sc); - mRS.setSurface(holder, w, h); - mRender = new BallsRS(); - mRender.init(mRS, getResources(), w, h); - } - mRender.updateProjectionMatrices(); - } - - @Override - protected void onDetachedFromWindow() { - if(mRS != null) { - mRS = null; - destroyRenderScriptGL(); - } - } - - - @Override - public boolean onTouchEvent(MotionEvent ev) - { - int act = ev.getActionMasked(); - if (act == ev.ACTION_UP) { - mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0)); - return false; - } else if (act == MotionEvent.ACTION_POINTER_UP) { - // only one pointer going up, we can get the index like this - int pointerIndex = ev.getActionIndex(); - int pointerId = ev.getPointerId(pointerIndex); - mRender.newTouchPosition(0, 0, 0, pointerId); - return false; - } - int count = ev.getHistorySize(); - int pcount = ev.getPointerCount(); - - for (int p=0; p < pcount; p++) { - int id = ev.getPointerId(p); - mRender.newTouchPosition(ev.getX(p), - ev.getY(p), - ev.getPressure(p), - id); - - for (int i=0; i < count; i++) { - mRender.newTouchPosition(ev.getHistoricalX(p, i), - ev.getHistoricalY(p, i), - ev.getHistoricalPressure(p, i), - id); - } - } - return true; - } - - void setAccel(float x, float y, float z) { - if (mRender == null) { - return; - } - mRender.setAccel(x, -y); - } - -} - - diff --git a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs b/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs deleted file mode 100644 index ff38be550f4c..000000000000 --- a/libs/rs/java/Balls/src/com/android/balls/ball_physics.rs +++ /dev/null @@ -1,146 +0,0 @@ -#pragma version(1) -#pragma rs java_package_name(com.android.balls) - -#include "balls.rsh" - -float2 gGravityVector = {0.f, 9.8f}; - -float2 gMinPos = {0.f, 0.f}; -float2 gMaxPos = {1280.f, 700.f}; - -static float2 touchPos[10]; -static float touchPressure[10]; - -void touch(float x, float y, float pressure, int id) { - if (id >= 10) { - return; - } - - touchPos[id].x = x; - touchPos[id].y = y; - touchPressure[id] = pressure; -} - -void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) { - float2 fv = {0, 0}; - float2 pos = ballIn->position; - - int arcID = -1; - float arcInvStr = 100000; - - const Ball_t * bPtr = rsGetElementAt(ctl->ain, 0); - for (uint32_t xin = 0; xin < ctl->dimX; xin++) { - float2 vec = bPtr[xin].position - pos; - float2 vec2 = vec * vec; - float len2 = vec2.x + vec2.y; - - if (len2 < 10000) { - //float minDist = ballIn->size + bPtr[xin].size; - float forceScale = ballIn->size * bPtr[xin].size; - forceScale *= forceScale; - - if (len2 > 16 /* (minDist*minDist)*/) { - // Repulsion - float len = sqrt(len2); - fv -= (vec / (len * len * len)) * 20000.f * forceScale; - } else { - if (len2 < 1) { - if (xin == x) { - continue; - } - ballOut->delta = 0.f; - ballOut->position = ballIn->position; - if (xin > x) { - ballOut->position.x += 1.f; - } else { - ballOut->position.x -= 1.f; - } - //ballOut->color.rgb = 1.f; - //ballOut->arcID = -1; - //ballOut->arcStr = 0; - return; - } - // Collision - float2 axis = normalize(vec); - float e1 = dot(axis, ballIn->delta); - float e2 = dot(axis, bPtr[xin].delta); - float e = (e1 - e2) * 0.45f; - if (e1 > 0) { - fv -= axis * e; - } else { - fv += axis * e; - } - } - } - } - - fv /= ballIn->size * ballIn->size * ballIn->size; - fv -= gGravityVector * 4.f; - fv *= ctl->dt; - - for (int i=0; i < 10; i++) { - if (touchPressure[i] > 0.1f) { - float2 vec = touchPos[i] - ballIn->position; - float2 vec2 = vec * vec; - float len2 = max(2.f, vec2.x + vec2.y); - fv -= (vec / len2) * touchPressure[i] * 300.f; - } - } - - ballOut->delta = (ballIn->delta * (1.f - 0.004f)) + fv; - ballOut->position = ballIn->position + (ballOut->delta * ctl->dt); - - const float wallForce = 400.f; - if (ballOut->position.x > (gMaxPos.x - 20.f)) { - float d = gMaxPos.x - ballOut->position.x; - if (d < 0.f) { - if (ballOut->delta.x > 0) { - ballOut->delta.x *= -0.7; - } - ballOut->position.x = gMaxPos.x; - } else { - ballOut->delta.x -= min(wallForce / (d * d), 10.f); - } - } - - if (ballOut->position.x < (gMinPos.x + 20.f)) { - float d = ballOut->position.x - gMinPos.x; - if (d < 0.f) { - if (ballOut->delta.x < 0) { - ballOut->delta.x *= -0.7; - } - ballOut->position.x = gMinPos.x + 1.f; - } else { - ballOut->delta.x += min(wallForce / (d * d), 10.f); - } - } - - if (ballOut->position.y > (gMaxPos.y - 20.f)) { - float d = gMaxPos.y - ballOut->position.y; - if (d < 0.f) { - if (ballOut->delta.y > 0) { - ballOut->delta.y *= -0.7; - } - ballOut->position.y = gMaxPos.y; - } else { - ballOut->delta.y -= min(wallForce / (d * d), 10.f); - } - } - - if (ballOut->position.y < (gMinPos.y + 20.f)) { - float d = ballOut->position.y - gMinPos.y; - if (d < 0.f) { - if (ballOut->delta.y < 0) { - ballOut->delta.y *= -0.7; - } - ballOut->position.y = gMinPos.y + 1.f; - } else { - ballOut->delta.y += min(wallForce / (d * d * d), 10.f); - } - } - - ballOut->size = ballIn->size; - - //rsDebug("physics pos out", ballOut->position); -} - diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rs b/libs/rs/java/Balls/src/com/android/balls/balls.rs deleted file mode 100644 index 7dc7660b15e6..000000000000 --- a/libs/rs/java/Balls/src/com/android/balls/balls.rs +++ /dev/null @@ -1,85 +0,0 @@ -#pragma version(1) -#pragma rs java_package_name(com.android.balls) -#include "rs_graphics.rsh" - -#include "balls.rsh" - -#pragma stateVertex(parent) -#pragma stateStore(parent) - -rs_program_fragment gPFPoints; -rs_program_fragment gPFLines; -rs_mesh partMesh; - -typedef struct __attribute__((packed, aligned(4))) Point { - float2 position; - float size; -} Point_t; -Point_t *point; - -typedef struct VpConsts { - rs_matrix4x4 MVP; -} VpConsts_t; -VpConsts_t *vpConstants; - -rs_script physics_script; - -Ball_t *balls1; -Ball_t *balls2; - -static int frame = 0; - -void initParts(int w, int h) -{ - uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls1)); - - for (uint32_t ct=0; ct < dimX; ct++) { - balls1[ct].position.x = rsRand(0.f, (float)w); - balls1[ct].position.y = rsRand(0.f, (float)h); - balls1[ct].delta.x = 0.f; - balls1[ct].delta.y = 0.f; - balls1[ct].size = 1.f; - - float r = rsRand(100.f); - if (r > 90.f) { - balls1[ct].size += pow(10.f, rsRand(0.f, 2.f)) * 0.07; - } - } -} - - - -int root() { - rsgClearColor(0.f, 0.f, 0.f, 1.f); - - BallControl_t bc; - Ball_t *bout; - - if (frame & 1) { - rsSetObject(&bc.ain, rsGetAllocation(balls2)); - rsSetObject(&bc.aout, rsGetAllocation(balls1)); - bout = balls2; - } else { - rsSetObject(&bc.ain, rsGetAllocation(balls1)); - rsSetObject(&bc.aout, rsGetAllocation(balls2)); - bout = balls1; - } - - bc.dimX = rsAllocationGetDimX(bc.ain); - bc.dt = 1.f / 30.f; - - rsForEach(physics_script, bc.ain, bc.aout, &bc); - - for (uint32_t ct=0; ct < bc.dimX; ct++) { - point[ct].position = bout[ct].position; - point[ct].size = 6.f /*+ bout[ct].color.g * 6.f*/ * bout[ct].size; - } - - frame++; - rsgBindProgramFragment(gPFPoints); - rsgDrawMesh(partMesh); - rsClearObject(&bc.ain); - rsClearObject(&bc.aout); - return 1; -} - diff --git a/libs/rs/java/Balls/src/com/android/balls/balls.rsh b/libs/rs/java/Balls/src/com/android/balls/balls.rsh deleted file mode 100644 index fc886f9fb0ec..000000000000 --- a/libs/rs/java/Balls/src/com/android/balls/balls.rsh +++ /dev/null @@ -1,18 +0,0 @@ - -typedef struct __attribute__((packed, aligned(4))) Ball { - float2 delta; - float2 position; - //float3 color; - float size; - //int arcID; - //float arcStr; -} Ball_t; -Ball_t *balls; - - -typedef struct BallControl { - uint32_t dimX; - rs_allocation ain; - rs_allocation aout; - float dt; -} BallControl_t; diff --git a/libs/rs/java/Fountain/Android.mk b/libs/rs/java/Fountain/Android.mk deleted file mode 100644 index 71944b2184dc..000000000000 --- a/libs/rs/java/Fountain/Android.mk +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -ifneq ($(TARGET_SIMULATOR),true) - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) -#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript - -LOCAL_PACKAGE_NAME := Fountain - -include $(BUILD_PACKAGE) - -endif diff --git a/libs/rs/java/Fountain/AndroidManifest.xml b/libs/rs/java/Fountain/AndroidManifest.xml deleted file mode 100644 index 5126e5c20815..000000000000 --- a/libs/rs/java/Fountain/AndroidManifest.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.fountain"> - <uses-sdk android:minSdkVersion="11" /> - <application - android:label="Fountain" - android:icon="@drawable/test_pattern"> - <activity android:name="Fountain"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/libs/rs/java/Fountain/_index.html b/libs/rs/java/Fountain/_index.html deleted file mode 100644 index 223242f73bc7..000000000000 --- a/libs/rs/java/Fountain/_index.html +++ /dev/null @@ -1,5 +0,0 @@ -<p>An example that renders many dots on the screen that follow a user's touch. The dots fall -to the bottom of the screen when the user releases the finger.</p> - - - diff --git a/libs/rs/java/Fountain/res/drawable/test_pattern.png b/libs/rs/java/Fountain/res/drawable/test_pattern.png Binary files differdeleted file mode 100644 index e7d145554c00..000000000000 --- a/libs/rs/java/Fountain/res/drawable/test_pattern.png +++ /dev/null diff --git a/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java b/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java deleted file mode 100644 index 116c478fcecd..000000000000 --- a/libs/rs/java/Fountain/src/com/android/fountain/Fountain.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.fountain; - -import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScript; - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.provider.Settings.System; -import android.util.Config; -import android.util.Log; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.Button; -import android.widget.ListView; - -import java.lang.Runtime; - -public class Fountain extends Activity { - //EventListener mListener = new EventListener(); - - private static final String LOG_TAG = "libRS_jni"; - private static final boolean DEBUG = false; - private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; - - private FountainView mView; - - // get the current looper (from your Activity UI thread for instance - - - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - // Create our Preview view and set it as the content of our - // Activity - mView = new FountainView(this); - setContentView(mView); - } - - @Override - protected void onResume() { - Log.e("rs", "onResume"); - - // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity looses focus - super.onResume(); - mView.resume(); - } - - @Override - protected void onPause() { - Log.e("rs", "onPause"); - - // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity looses focus - super.onPause(); - mView.pause(); - - - - //Runtime.getRuntime().exit(0); - } - - - static void log(String message) { - if (LOG_ENABLED) { - Log.v(LOG_TAG, message); - } - } - - -} - diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java deleted file mode 100644 index be2f9caefa03..000000000000 --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainRS.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.fountain; - -import android.content.res.Resources; -import android.renderscript.*; -import android.util.Log; - - -public class FountainRS { - public static final int PART_COUNT = 50000; - - public FountainRS() { - } - - private Resources mRes; - private RenderScriptGL mRS; - private ScriptC_fountain mScript; - public void init(RenderScriptGL rs, Resources res, int width, int height) { - mRS = rs; - mRes = res; - - ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs); - pfb.setVaryingColor(true); - rs.bindProgramFragment(pfb.create()); - - ScriptField_Point points = new ScriptField_Point(mRS, PART_COUNT);// - // Allocation.USAGE_GRAPHICS_VERTEX); - - Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS); - smb.addVertexAllocation(points.getAllocation()); - smb.addIndexSetType(Mesh.Primitive.POINT); - Mesh sm = smb.create(); - - mScript = new ScriptC_fountain(mRS, mRes, R.raw.fountain); - mScript.set_partMesh(sm); - mScript.bind_point(points); - mRS.bindRootScript(mScript); - } - - boolean holdingColor[] = new boolean[10]; - public void newTouchPosition(float x, float y, float pressure, int id) { - if (id >= holdingColor.length) { - return; - } - int rate = (int)(pressure * pressure * 500.f); - if (rate > 500) { - rate = 500; - } - if (rate > 0) { - mScript.invoke_addParticles(rate, x, y, id, !holdingColor[id]); - holdingColor[id] = true; - } else { - holdingColor[id] = false; - } - - } -} diff --git a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java b/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java deleted file mode 100644 index 69b181dba47b..000000000000 --- a/libs/rs/java/Fountain/src/com/android/fountain/FountainView.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.fountain; - -import java.io.Writer; -import java.util.ArrayList; -import java.util.concurrent.Semaphore; - -import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScript; -import android.renderscript.RenderScriptGL; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.os.Handler; -import android.os.Message; -import android.util.AttributeSet; -import android.util.Log; -import android.view.Surface; -import android.view.SurfaceHolder; -import android.view.SurfaceView; -import android.view.KeyEvent; -import android.view.MotionEvent; - -public class FountainView extends RSSurfaceView { - - public FountainView(Context context) { - super(context); - //setFocusable(true); - } - - private RenderScriptGL mRS; - private FountainRS mRender; - - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - super.surfaceChanged(holder, format, w, h); - if (mRS == null) { - RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); - mRS = createRenderScriptGL(sc); - mRS.setSurface(holder, w, h); - mRender = new FountainRS(); - mRender.init(mRS, getResources(), w, h); - } - } - - @Override - protected void onDetachedFromWindow() { - if (mRS != null) { - mRS = null; - destroyRenderScriptGL(); - } - } - - - @Override - public boolean onTouchEvent(MotionEvent ev) - { - int act = ev.getActionMasked(); - if (act == ev.ACTION_UP) { - mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0)); - return false; - } else if (act == MotionEvent.ACTION_POINTER_UP) { - // only one pointer going up, we can get the index like this - int pointerIndex = ev.getActionIndex(); - int pointerId = ev.getPointerId(pointerIndex); - mRender.newTouchPosition(0, 0, 0, pointerId); - } - int count = ev.getHistorySize(); - int pcount = ev.getPointerCount(); - - for (int p=0; p < pcount; p++) { - int id = ev.getPointerId(p); - mRender.newTouchPosition(ev.getX(p), - ev.getY(p), - ev.getPressure(p), - id); - - for (int i=0; i < count; i++) { - mRender.newTouchPosition(ev.getHistoricalX(p, i), - ev.getHistoricalY(p, i), - ev.getHistoricalPressure(p, i), - id); - } - } - return true; - } -} - - diff --git a/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs b/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs deleted file mode 100644 index b8f57a33c4a4..000000000000 --- a/libs/rs/java/Fountain/src/com/android/fountain/fountain.rs +++ /dev/null @@ -1,69 +0,0 @@ -// Fountain test script -#pragma version(1) - -#pragma rs java_package_name(com.android.fountain) - -#pragma stateFragment(parent) - -#include "rs_graphics.rsh" - -static int newPart = 0; -rs_mesh partMesh; - -typedef struct __attribute__((packed, aligned(4))) Point { - float2 delta; - float2 position; - uchar4 color; -} Point_t; -Point_t *point; - -int root() { - float dt = min(rsGetDt(), 0.1f); - rsgClearColor(0.f, 0.f, 0.f, 1.f); - const float height = rsgGetHeight(); - const int size = rsAllocationGetDimX(rsGetAllocation(point)); - float dy2 = dt * (10.f); - Point_t * p = point; - for (int ct=0; ct < size; ct++) { - p->delta.y += dy2; - p->position += p->delta; - if ((p->position.y > height) && (p->delta.y > 0)) { - p->delta.y *= -0.3f; - } - p++; - } - - rsgDrawMesh(partMesh); - return 1; -} - -static float4 partColor[10]; -void addParticles(int rate, float x, float y, int index, bool newColor) -{ - if (newColor) { - partColor[index].x = rsRand(0.5f, 1.0f); - partColor[index].y = rsRand(1.0f); - partColor[index].z = rsRand(1.0f); - } - float rMax = ((float)rate) * 0.02f; - int size = rsAllocationGetDimX(rsGetAllocation(point)); - uchar4 c = rsPackColorTo8888(partColor[index]); - - Point_t * np = &point[newPart]; - float2 p = {x, y}; - while (rate--) { - float angle = rsRand(3.14f * 2.f); - float len = rsRand(rMax); - np->delta.x = len * sin(angle); - np->delta.y = len * cos(angle); - np->position = p; - np->color = c; - newPart++; - np++; - if (newPart >= size) { - newPart = 0; - np = &point[newPart]; - } - } -} - diff --git a/libs/rs/java/HelloCompute/Android.mk b/libs/rs/java/HelloCompute/Android.mk deleted file mode 100644 index 3881bb0383be..000000000000 --- a/libs/rs/java/HelloCompute/Android.mk +++ /dev/null @@ -1,31 +0,0 @@ -# -# 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. -# - -ifneq ($(TARGET_SIMULATOR),true) - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-java-files-under, src) \ - $(call all-renderscript-files-under, src) - -LOCAL_PACKAGE_NAME := HelloCompute - -include $(BUILD_PACKAGE) - -endif diff --git a/libs/rs/java/HelloCompute/_index.html b/libs/rs/java/HelloCompute/_index.html deleted file mode 100644 index abfd9784a958..000000000000 --- a/libs/rs/java/HelloCompute/_index.html +++ /dev/null @@ -1,2 +0,0 @@ -<p>A Renderscript compute sample that filters a bitmap. No Renderscript graphics APIs are used -in this sample.</p>
\ No newline at end of file diff --git a/libs/rs/java/HelloCompute/res/drawable/data.jpg b/libs/rs/java/HelloCompute/res/drawable/data.jpg Binary files differdeleted file mode 100644 index 81a87b1726c2..000000000000 --- a/libs/rs/java/HelloCompute/res/drawable/data.jpg +++ /dev/null diff --git a/libs/rs/java/HelloCompute/src/com/android/example/hellocompute/HelloCompute.java b/libs/rs/java/HelloCompute/src/com/android/example/hellocompute/HelloCompute.java deleted file mode 100644 index 123c37bb7f72..000000000000 --- a/libs/rs/java/HelloCompute/src/com/android/example/hellocompute/HelloCompute.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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.android.example.hellocompute; - -import android.app.Activity; -import android.os.Bundle; -import android.graphics.BitmapFactory; -import android.graphics.Bitmap; -import android.renderscript.RenderScript; -import android.renderscript.Allocation; -import android.widget.ImageView; - -public class HelloCompute extends Activity { - private Bitmap mBitmapIn; - private Bitmap mBitmapOut; - - private RenderScript mRS; - private Allocation mInAllocation; - private Allocation mOutAllocation; - private ScriptC_mono mScript; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.main); - - mBitmapIn = loadBitmap(R.drawable.data); - mBitmapOut = Bitmap.createBitmap(mBitmapIn.getWidth(), mBitmapIn.getHeight(), - mBitmapIn.getConfig()); - - ImageView in = (ImageView) findViewById(R.id.displayin); - in.setImageBitmap(mBitmapIn); - - ImageView out = (ImageView) findViewById(R.id.displayout); - out.setImageBitmap(mBitmapOut); - - createScript(); - } - - - private void createScript() { - mRS = RenderScript.create(this); - - mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn, - Allocation.MipmapControl.MIPMAP_NONE, - Allocation.USAGE_SCRIPT); - mOutAllocation = Allocation.createTyped(mRS, mInAllocation.getType()); - - mScript = new ScriptC_mono(mRS, getResources(), R.raw.mono); - - mScript.set_gIn(mInAllocation); - mScript.set_gOut(mOutAllocation); - mScript.set_gScript(mScript); - mScript.invoke_filter(); - mOutAllocation.copyTo(mBitmapOut); - } - - private Bitmap loadBitmap(int resource) { - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - return BitmapFactory.decodeResource(getResources(), resource, options); - } -} diff --git a/libs/rs/java/HelloWorld/Android.mk b/libs/rs/java/HelloWorld/Android.mk deleted file mode 100644 index 72f0f03b2187..000000000000 --- a/libs/rs/java/HelloWorld/Android.mk +++ /dev/null @@ -1,30 +0,0 @@ -# -# 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. -# - -ifneq ($(TARGET_SIMULATOR),true) - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) - -LOCAL_PACKAGE_NAME := HelloWorld - -include $(BUILD_PACKAGE) - -endif diff --git a/libs/rs/java/HelloWorld/_index.html b/libs/rs/java/HelloWorld/_index.html deleted file mode 100644 index 4cab73817684..000000000000 --- a/libs/rs/java/HelloWorld/_index.html +++ /dev/null @@ -1 +0,0 @@ -<p>A Renderscript graphics application that draws the text "Hello, World!" where the user touches.</p>
\ No newline at end of file diff --git a/libs/rs/java/HelloWorld/res/drawable/test_pattern.png b/libs/rs/java/HelloWorld/res/drawable/test_pattern.png Binary files differdeleted file mode 100644 index e7d145554c00..000000000000 --- a/libs/rs/java/HelloWorld/res/drawable/test_pattern.png +++ /dev/null diff --git a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorld.java b/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorld.java deleted file mode 100644 index f63015e7b596..000000000000 --- a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorld.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.android.rs.helloworld; - -import android.app.Activity; -import android.os.Bundle; - -// Renderscript activity -public class HelloWorld extends Activity { - - // Custom view to use with RenderScript - private HelloWorldView mView; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - // Create our view and set it as the content of our Activity - mView = new HelloWorldView(this); - setContentView(mView); - } - - @Override - protected void onResume() { - // Ideally an app should implement onResume() and onPause() - // to take appropriate action when the activity loses focus - super.onResume(); - mView.resume(); - } - - @Override - protected void onPause() { - // Ideally an app should implement onResume() and onPause() - // to take appropriate action when the activity loses focus - super.onPause(); - mView.pause(); - } - -} - diff --git a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorldRS.java b/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorldRS.java deleted file mode 100644 index c9c1316f01b5..000000000000 --- a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorldRS.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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.android.rs.helloworld; - -import android.content.res.Resources; -import android.renderscript.*; - -// This is the renderer for the HelloWorldView -public class HelloWorldRS { - private Resources mRes; - private RenderScriptGL mRS; - - private ScriptC_helloworld mScript; - - public HelloWorldRS() { - } - - // This provides us with the renderscript context and resources that - // allow us to create the script that does rendering - public void init(RenderScriptGL rs, Resources res) { - mRS = rs; - mRes = res; - initRS(); - } - - public void onActionDown(int x, int y) { - mScript.set_gTouchX(x); - mScript.set_gTouchY(y); - } - - private void initRS() { - mScript = new ScriptC_helloworld(mRS, mRes, R.raw.helloworld); - mRS.bindRootScript(mScript); - } -} - - - diff --git a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorldView.java b/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorldView.java deleted file mode 100644 index 8cddb2a7a77e..000000000000 --- a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/HelloWorldView.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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.android.rs.helloworld; - -import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScriptGL; - -import android.content.Context; -import android.view.MotionEvent; - -public class HelloWorldView extends RSSurfaceView { - // Renderscipt context - private RenderScriptGL mRS; - // Script that does the rendering - private HelloWorldRS mRender; - - public HelloWorldView(Context context) { - super(context); - ensureRenderScript(); - } - - private void ensureRenderScript() { - if (mRS == null) { - // Initialize renderscript with desired surface characteristics. - // In this case, just use the defaults - RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); - mRS = createRenderScriptGL(sc); - // Create an instance of the script that does the rendering - mRender = new HelloWorldRS(); - mRender.init(mRS, getResources()); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - ensureRenderScript(); - } - - @Override - protected void onDetachedFromWindow() { - // Handle the system event and clean up - mRender = null; - if (mRS != null) { - mRS = null; - destroyRenderScriptGL(); - } - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - // Pass touch events from the system to the rendering script - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - mRender.onActionDown((int)ev.getX(), (int)ev.getY()); - return true; - } - - return false; - } -} - - diff --git a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/helloworld.rs b/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/helloworld.rs deleted file mode 100644 index fa171f56e1a7..000000000000 --- a/libs/rs/java/HelloWorld/src/com/android/rs/helloworld/helloworld.rs +++ /dev/null @@ -1,47 +0,0 @@ -// 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. - -#pragma version(1) - -// Tell which java package name the reflected files should belong to -#pragma rs java_package_name(com.android.rs.helloworld) - -// Built-in header with graphics API's -#include "rs_graphics.rsh" - -// gTouchX and gTouchY are variables that will be reflected for use -// by the java API. We can use them to notify the script of touch events. -int gTouchX; -int gTouchY; - -// This is invoked automatically when the script is created -void init() { - gTouchX = 50.0f; - gTouchY = 50.0f; -} - -int root(int launchID) { - - // Clear the background color - rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f); - // Tell the runtime what the font color should be - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - // Introuduce ourselves to the world by drawing a greeting - // at the position user touched on the screen - rsgDrawText("Hello World!", gTouchX, gTouchY); - - // Return value tells RS roughly how often to redraw - // in this case 20 ms - return 20; -} diff --git a/libs/rs/java/Samples/Android.mk b/libs/rs/java/Samples/Android.mk deleted file mode 100644 index 65ae734e5c70..000000000000 --- a/libs/rs/java/Samples/Android.mk +++ /dev/null @@ -1,31 +0,0 @@ -# -# Copyright (C) 2008 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -ifneq ($(TARGET_SIMULATOR),true) - -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE_TAGS := optional - -LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) -#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript - -LOCAL_PACKAGE_NAME := Samples - -include $(BUILD_PACKAGE) - -endif diff --git a/libs/rs/java/Samples/AndroidManifest.xml b/libs/rs/java/Samples/AndroidManifest.xml deleted file mode 100644 index c08a264de070..000000000000 --- a/libs/rs/java/Samples/AndroidManifest.xml +++ /dev/null @@ -1,25 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<manifest xmlns:android="http://schemas.android.com/apk/res/android" - package="com.android.samples"> - <uses-sdk android:minSdkVersion="11" /> - <application android:label="Samples" - android:icon="@drawable/test_pattern"> - <activity android:name="RsList" - android:label="RsList" - android:theme="@android:style/Theme.Black.NoTitleBar"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - - <activity android:name="RsRenderStates" - android:label="RsStates" - android:theme="@android:style/Theme.Black.NoTitleBar"> - <intent-filter> - <action android:name="android.intent.action.MAIN" /> - <category android:name="android.intent.category.LAUNCHER" /> - </intent-filter> - </activity> - </application> -</manifest> diff --git a/libs/rs/java/Samples/_index.html b/libs/rs/java/Samples/_index.html deleted file mode 100644 index 5872431420e6..000000000000 --- a/libs/rs/java/Samples/_index.html +++ /dev/null @@ -1 +0,0 @@ -<p>A set of samples that demonstrate how to use various features of the Renderscript APIs.</p>
\ No newline at end of file diff --git a/libs/rs/java/Samples/res/drawable/checker.png b/libs/rs/java/Samples/res/drawable/checker.png Binary files differdeleted file mode 100644 index b631e1ee4ba6..000000000000 --- a/libs/rs/java/Samples/res/drawable/checker.png +++ /dev/null diff --git a/libs/rs/java/Samples/res/drawable/cubemap_test.png b/libs/rs/java/Samples/res/drawable/cubemap_test.png Binary files differdeleted file mode 100644 index baf35d0acbe9..000000000000 --- a/libs/rs/java/Samples/res/drawable/cubemap_test.png +++ /dev/null diff --git a/libs/rs/java/Samples/res/drawable/data.png b/libs/rs/java/Samples/res/drawable/data.png Binary files differdeleted file mode 100644 index 8e347146e331..000000000000 --- a/libs/rs/java/Samples/res/drawable/data.png +++ /dev/null diff --git a/libs/rs/java/Samples/res/drawable/leaf.png b/libs/rs/java/Samples/res/drawable/leaf.png Binary files differdeleted file mode 100644 index 3cd37755f549..000000000000 --- a/libs/rs/java/Samples/res/drawable/leaf.png +++ /dev/null diff --git a/libs/rs/java/Samples/res/drawable/test_pattern.png b/libs/rs/java/Samples/res/drawable/test_pattern.png Binary files differdeleted file mode 100644 index e7d145554c00..000000000000 --- a/libs/rs/java/Samples/res/drawable/test_pattern.png +++ /dev/null diff --git a/libs/rs/java/Samples/res/drawable/torusmap.png b/libs/rs/java/Samples/res/drawable/torusmap.png Binary files differdeleted file mode 100644 index 1e08f3b9ac3e..000000000000 --- a/libs/rs/java/Samples/res/drawable/torusmap.png +++ /dev/null diff --git a/libs/rs/java/Samples/res/raw/multitexf.glsl b/libs/rs/java/Samples/res/raw/multitexf.glsl deleted file mode 100644 index e492a477ff5b..000000000000 --- a/libs/rs/java/Samples/res/raw/multitexf.glsl +++ /dev/null @@ -1,13 +0,0 @@ -varying vec2 varTex0; - -void main() { - vec2 t0 = varTex0.xy; - lowp vec4 col0 = texture2D(UNI_Tex0, t0).rgba; - lowp vec4 col1 = texture2D(UNI_Tex1, t0*4.0).rgba; - lowp vec4 col2 = texture2D(UNI_Tex2, t0).rgba; - col0.xyz = col0.xyz*col1.xyz*1.5; - col0.xyz = mix(col0.xyz, col2.xyz, col2.w); - col0.w = 0.5; - gl_FragColor = col0; -} - diff --git a/libs/rs/java/Samples/res/raw/shader2f.glsl b/libs/rs/java/Samples/res/raw/shader2f.glsl deleted file mode 100644 index 5fc05f14a812..000000000000 --- a/libs/rs/java/Samples/res/raw/shader2f.glsl +++ /dev/null @@ -1,29 +0,0 @@ -varying vec3 varWorldPos; -varying vec3 varWorldNormal; -varying vec2 varTex0; - -void main() { - - vec3 V = normalize(-varWorldPos.xyz); - vec3 worldNorm = normalize(varWorldNormal); - - vec3 light0Vec = normalize(UNI_light0_Posision.xyz - varWorldPos); - vec3 light0R = -reflect(light0Vec, worldNorm); - float light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse; - float light0Spec = clamp(dot(light0R, V), 0.001, 1.0); - float light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular; - - vec3 light1Vec = normalize(UNI_light1_Posision.xyz - varWorldPos); - vec3 light1R = reflect(light1Vec, worldNorm); - float light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse; - float light1Spec = clamp(dot(light1R, V), 0.001, 1.0); - float light1_Specular = pow(light1Spec, UNI_light1_CosinePower) * UNI_light1_Specular; - - vec2 t0 = varTex0.xy; - lowp vec4 col = texture2D(UNI_Tex0, t0).rgba; - col.xyz = col.xyz * (light0_Diffuse * UNI_light0_DiffuseColor.xyz + light1_Diffuse * UNI_light1_DiffuseColor.xyz); - col.xyz += light0_Specular * UNI_light0_SpecularColor.xyz; - col.xyz += light1_Specular * UNI_light1_SpecularColor.xyz; - gl_FragColor = col; -} - diff --git a/libs/rs/java/Samples/res/raw/shader2movev.glsl b/libs/rs/java/Samples/res/raw/shader2movev.glsl deleted file mode 100644 index a2c807e838cc..000000000000 --- a/libs/rs/java/Samples/res/raw/shader2movev.glsl +++ /dev/null @@ -1,21 +0,0 @@ -varying vec3 varWorldPos; -varying vec3 varWorldNormal; -varying vec2 varTex0; - -// This is where actual shader code begins -void main() { - vec4 objPos = ATTRIB_position; - vec3 oldPos = objPos.xyz; - objPos.xyz += 0.1*sin(objPos.xyz*2.0 + UNI_time); - objPos.xyz += 0.05*sin(objPos.xyz*4.0 + UNI_time*0.5); - objPos.xyz += 0.02*sin(objPos.xyz*7.0 + UNI_time*0.75); - vec4 worldPos = UNI_model * objPos; - gl_Position = UNI_proj * worldPos; - - mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); - vec3 worldNorm = model3 * (ATTRIB_normal + oldPos - objPos.xyz); - - varWorldPos = worldPos.xyz; - varWorldNormal = worldNorm; - varTex0 = ATTRIB_texture0; -} diff --git a/libs/rs/java/Samples/res/raw/shader2v.glsl b/libs/rs/java/Samples/res/raw/shader2v.glsl deleted file mode 100644 index e6885a38aca0..000000000000 --- a/libs/rs/java/Samples/res/raw/shader2v.glsl +++ /dev/null @@ -1,17 +0,0 @@ -varying vec3 varWorldPos; -varying vec3 varWorldNormal; -varying vec2 varTex0; - -// This is where actual shader code begins -void main() { - vec4 objPos = ATTRIB_position; - vec4 worldPos = UNI_model * objPos; - gl_Position = UNI_proj * worldPos; - - mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); - vec3 worldNorm = model3 * ATTRIB_normal; - - varWorldPos = worldPos.xyz; - varWorldNormal = worldNorm; - varTex0 = ATTRIB_texture0; -} diff --git a/libs/rs/java/Samples/res/raw/shaderarrayf.glsl b/libs/rs/java/Samples/res/raw/shaderarrayf.glsl deleted file mode 100644 index 238ecad56cf1..000000000000 --- a/libs/rs/java/Samples/res/raw/shaderarrayf.glsl +++ /dev/null @@ -1,16 +0,0 @@ - -varying lowp float light0_Diffuse; -varying lowp float light0_Specular; -varying lowp float light1_Diffuse; -varying lowp float light1_Specular; -varying vec2 varTex0; - -void main() { - vec2 t0 = varTex0.xy; - lowp vec4 col = texture2D(UNI_Tex0, t0).rgba; - col.xyz = col.xyz * (light0_Diffuse * UNI_light_DiffuseColor[0].xyz + light1_Diffuse * UNI_light_DiffuseColor[1].xyz); - col.xyz += light0_Specular * UNI_light_SpecularColor[0].xyz; - col.xyz += light1_Specular * UNI_light_SpecularColor[1].xyz; - gl_FragColor = col; -} - diff --git a/libs/rs/java/Samples/res/raw/shaderarrayv.glsl b/libs/rs/java/Samples/res/raw/shaderarrayv.glsl deleted file mode 100644 index 7a1310ac1ef4..000000000000 --- a/libs/rs/java/Samples/res/raw/shaderarrayv.glsl +++ /dev/null @@ -1,32 +0,0 @@ -varying float light0_Diffuse; -varying float light0_Specular; -varying float light1_Diffuse; -varying float light1_Specular; -varying vec2 varTex0; - -// This is where actual shader code begins -void main() { - vec4 worldPos = UNI_model[0] * ATTRIB_position; - worldPos = UNI_model[1] * worldPos; - gl_Position = UNI_proj * worldPos; - - mat4 model0 = UNI_model[0]; - mat3 model3 = mat3(model0[0].xyz, model0[1].xyz, model0[2].xyz); - vec3 worldNorm = model3 * ATTRIB_normal; - vec3 V = normalize(-worldPos.xyz); - - vec3 light0Vec = normalize(UNI_light_Posision[0].xyz - worldPos.xyz); - vec3 light0R = -reflect(light0Vec, worldNorm); - light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light_Diffuse[0]; - float light0Spec = clamp(dot(light0R, V), 0.001, 1.0); - light0_Specular = pow(light0Spec, UNI_light_CosinePower[0]) * UNI_light_Specular[0]; - - vec3 light1Vec = normalize(UNI_light_Posision[1].xyz - worldPos.xyz); - vec3 light1R = reflect(light1Vec, worldNorm); - light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light_Diffuse[1]; - float light1Spec = clamp(dot(light1R, V), 0.001, 1.0); - light1_Specular = pow(light1Spec, UNI_light_CosinePower[1]) * UNI_light_Specular[1]; - - gl_PointSize = 1.0; - varTex0 = ATTRIB_texture0; -} diff --git a/libs/rs/java/Samples/res/raw/shadercubef.glsl b/libs/rs/java/Samples/res/raw/shadercubef.glsl deleted file mode 100644 index 15696a4723d5..000000000000 --- a/libs/rs/java/Samples/res/raw/shadercubef.glsl +++ /dev/null @@ -1,8 +0,0 @@ - -varying vec3 worldNormal; - -void main() { - lowp vec4 col = textureCube(UNI_Tex0, worldNormal); - gl_FragColor = col; -} - diff --git a/libs/rs/java/Samples/res/raw/shadercubev.glsl b/libs/rs/java/Samples/res/raw/shadercubev.glsl deleted file mode 100644 index 70f5cd64e371..000000000000 --- a/libs/rs/java/Samples/res/raw/shadercubev.glsl +++ /dev/null @@ -1,10 +0,0 @@ -varying vec3 worldNormal; - -// This is where actual shader code begins -void main() { - vec4 worldPos = UNI_model * ATTRIB_position; - gl_Position = UNI_proj * worldPos; - - mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); - worldNormal = model3 * ATTRIB_normal; -} diff --git a/libs/rs/java/Samples/res/raw/shaderf.glsl b/libs/rs/java/Samples/res/raw/shaderf.glsl deleted file mode 100644 index d56e203496c3..000000000000 --- a/libs/rs/java/Samples/res/raw/shaderf.glsl +++ /dev/null @@ -1,16 +0,0 @@ - -varying lowp float light0_Diffuse; -varying lowp float light0_Specular; -varying lowp float light1_Diffuse; -varying lowp float light1_Specular; -varying vec2 varTex0; - -void main() { - vec2 t0 = varTex0.xy; - lowp vec4 col = texture2D(UNI_Tex0, t0).rgba; - col.xyz = col.xyz * (light0_Diffuse * UNI_light0_DiffuseColor.xyz + light1_Diffuse * UNI_light1_DiffuseColor.xyz); - col.xyz += light0_Specular * UNI_light0_SpecularColor.xyz; - col.xyz += light1_Specular * UNI_light1_SpecularColor.xyz; - gl_FragColor = col; -} - diff --git a/libs/rs/java/Samples/res/raw/shaderv.glsl b/libs/rs/java/Samples/res/raw/shaderv.glsl deleted file mode 100644 index f7d01de384cb..000000000000 --- a/libs/rs/java/Samples/res/raw/shaderv.glsl +++ /dev/null @@ -1,30 +0,0 @@ -varying float light0_Diffuse; -varying float light0_Specular; -varying float light1_Diffuse; -varying float light1_Specular; -varying vec2 varTex0; - -// This is where actual shader code begins -void main() { - vec4 worldPos = UNI_model * ATTRIB_position; - gl_Position = UNI_proj * worldPos; - - mat3 model3 = mat3(UNI_model[0].xyz, UNI_model[1].xyz, UNI_model[2].xyz); - vec3 worldNorm = model3 * ATTRIB_normal; - vec3 V = normalize(-worldPos.xyz); - - vec3 light0Vec = normalize(UNI_light0_Posision.xyz - worldPos.xyz); - vec3 light0R = -reflect(light0Vec, worldNorm); - light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse; - float light0Spec = clamp(dot(light0R, V), 0.001, 1.0); - light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular; - - vec3 light1Vec = normalize(UNI_light1_Posision.xyz - worldPos.xyz); - vec3 light1R = reflect(light1Vec, worldNorm); - light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse; - float light1Spec = clamp(dot(light1R, V), 0.001, 1.0); - light1_Specular = pow(light1Spec, UNI_light1_CosinePower) * UNI_light1_Specular; - - gl_PointSize = 1.0; - varTex0 = ATTRIB_texture0; -} diff --git a/libs/rs/java/Samples/res/raw/torus.a3d b/libs/rs/java/Samples/res/raw/torus.a3d Binary files differdeleted file mode 100644 index 0322b01be8a8..000000000000 --- a/libs/rs/java/Samples/res/raw/torus.a3d +++ /dev/null diff --git a/libs/rs/java/Samples/src/com/android/samples/RsList.java b/libs/rs/java/Samples/src/com/android/samples/RsList.java deleted file mode 100644 index 2d7add0c5eed..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/RsList.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.samples; - -import android.app.Activity; -import android.os.Bundle; - -public class RsList extends Activity { - - private RsListView mView; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - // Create our Preview view and set it as the content of our - // Activity - mView = new RsListView(this); - setContentView(mView); - } - - @Override - protected void onResume() { - // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity loses focus - super.onResume(); - mView.resume(); - } - - @Override - protected void onPause() { - // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity loses focus - super.onPause(); - mView.pause(); - } - -} - diff --git a/libs/rs/java/Samples/src/com/android/samples/RsListRS.java b/libs/rs/java/Samples/src/com/android/samples/RsListRS.java deleted file mode 100644 index 6ee545ac5a58..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/RsListRS.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.samples; - -import java.io.Writer; -import java.util.Vector; - -import android.content.res.Resources; -import android.renderscript.*; -import android.renderscript.ProgramStore.DepthFunc; -import android.util.Log; - - -public class RsListRS { - - private final int STATE_LAST_FOCUS = 1; - - private static final String[] DATA_LIST = { - "Afghanistan", "Albania", "Algeria", "American Samoa", "Andorra", - "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", - "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", - "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", - "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", - "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", - "British Indian Ocean Territory", "British Virgin Islands", "Brunei", "Bulgaria", - "Burkina Faso", "Burundi", "Cote d'Ivoire", "Cambodia", "Cameroon", "Canada", "Cape Verde", - "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", - "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", - "Cook Islands", "Costa Rica", "Croatia", "Cuba", "Cyprus", "Czech Republic", - "Democratic Republic of the Congo", "Denmark", "Djibouti", "Dominica", "Dominican Republic", - "East Timor", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", - "Estonia", "Ethiopia", "Faeroe Islands", "Falkland Islands", "Fiji", "Finland", - "Former Yugoslav Republic of Macedonia", "France", "French Guiana", "French Polynesia", - "French Southern Territories", "Gabon", "Georgia", "Germany", "Ghana", "Gibraltar", - "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guinea", "Guinea-Bissau", - "Guyana", "Haiti", "Heard Island and McDonald Islands", "Honduras", "Hong Kong", "Hungary", - "Iceland", "India", "Indonesia", "Iran", "Iraq", "Ireland", "Israel", "Italy", "Jamaica", - "Japan", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Kuwait", "Kyrgyzstan", "Laos", - "Latvia", "Lebanon", "Lesotho", "Liberia", "Libya", "Liechtenstein", "Lithuania", "Luxembourg", - "Macau", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", - "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia", "Moldova", - "Monaco", "Mongolia", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", - "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", - "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "North Korea", "Northern Marianas", - "Norway", "Oman", "Pakistan", "Palau", "Panama", "Papua New Guinea", "Paraguay", "Peru", - "Philippines", "Pitcairn Islands", "Poland", "Portugal", "Puerto Rico", "Qatar", - "Reunion", "Romania", "Russia", "Rwanda", "Sqo Tome and Principe", "Saint Helena", - "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon", - "Saint Vincent and the Grenadines", "Samoa", "San Marino", "Saudi Arabia", "Senegal", - "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", - "Somalia", "South Africa", "South Georgia and the South Sandwich Islands", "South Korea", - "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", - "Switzerland", "Syria", "Taiwan", "Tajikistan", "Tanzania", "Thailand", "The Bahamas", - "The Gambia", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", - "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Virgin Islands", "Uganda", - "Ukraine", "United Arab Emirates", "United Kingdom", - "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", - "Vanuatu", "Vatican City", "Venezuela", "Vietnam", "Wallis and Futuna", "Western Sahara", - "Yemen", "Yugoslavia", "Zambia", "Zimbabwe" - }; - - public RsListRS() { - } - - public void init(RenderScriptGL rs, Resources res) { - mRS = rs; - mRes = res; - initRS(); - } - - private Resources mRes; - private RenderScriptGL mRS; - private Font mItalic; - - ScriptField_ListAllocs_s mListAllocs; - - private ScriptC_rslist mScript; - - int mLastX; - int mLastY; - - public void onActionDown(int x, int y) { - mScript.set_gDY(0.0f); - - mLastX = x; - mLastY = y; - } - - public void onActionMove(int x, int y) { - int dx = mLastX - x; - int dy = mLastY - y; - - if (Math.abs(dy) <= 2) { - dy = 0; - } - - mScript.set_gDY(dy); - - mLastX = x; - mLastY = y; - } - - private void initRS() { - - mScript = new ScriptC_rslist(mRS, mRes, R.raw.rslist); - - mListAllocs = new ScriptField_ListAllocs_s(mRS, DATA_LIST.length); - for (int i = 0; i < DATA_LIST.length; i ++) { - ScriptField_ListAllocs_s.Item listElem = new ScriptField_ListAllocs_s.Item(); - listElem.text = Allocation.createFromString(mRS, DATA_LIST[i], Allocation.USAGE_SCRIPT); - mListAllocs.set(listElem, i, false); - } - - mListAllocs.copyAll(); - - mScript.bind_gList(mListAllocs); - - mItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8); - mScript.set_gItalic(mItalic); - - mRS.bindRootScript(mScript); - } -} - - - diff --git a/libs/rs/java/Samples/src/com/android/samples/RsListView.java b/libs/rs/java/Samples/src/com/android/samples/RsListView.java deleted file mode 100644 index b67bd48a8730..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/RsListView.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.samples; -import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScriptGL; - -import android.content.Context; -import android.view.MotionEvent; - -public class RsListView extends RSSurfaceView { - - public RsListView(Context context) { - super(context); - ensureRenderScript(); - } - - private RenderScriptGL mRS; - private RsListRS mRender; - - private void ensureRenderScript() { - if (mRS == null) { - RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); - mRS = createRenderScriptGL(sc); - mRender = new RsListRS(); - mRender.init(mRS, getResources()); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - ensureRenderScript(); - } - - @Override - protected void onDetachedFromWindow() { - mRender = null; - if (mRS != null) { - mRS = null; - destroyRenderScriptGL(); - } - } - - @Override - public boolean onTouchEvent(MotionEvent ev) - { - boolean ret = false; - int act = ev.getAction(); - if (act == MotionEvent.ACTION_DOWN) { - mRender.onActionDown((int)ev.getX(), (int)ev.getY()); - ret = true; - } else if (act == MotionEvent.ACTION_MOVE) { - mRender.onActionMove((int)ev.getX(), (int)ev.getY()); - ret = true; - } - - return ret; - } -} - - diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStates.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStates.java deleted file mode 100644 index ff8c2dec28d3..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStates.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.samples; - -import android.app.Activity; -import android.os.Bundle; - -public class RsRenderStates extends Activity { - - private RsRenderStatesView mView; - - @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); - - // Create our Preview view and set it as the content of our - // Activity - mView = new RsRenderStatesView(this); - setContentView(mView); - } - - @Override - protected void onResume() { - // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity looses focus - super.onResume(); - mView.resume(); - } - - @Override - protected void onPause() { - // Ideally a game should implement onResume() and onPause() - // to take appropriate action when the activity looses focus - super.onPause(); - mView.pause(); - } - -} - diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java deleted file mode 100644 index 49b65d6d95ed..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java +++ /dev/null @@ -1,422 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.samples; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.renderscript.*; -import android.renderscript.Font.Style; -import android.renderscript.Program.TextureType; -import android.renderscript.ProgramStore.DepthFunc; -import android.renderscript.ProgramStore.BlendSrcFunc; -import android.renderscript.ProgramStore.BlendDstFunc; -import android.renderscript.Sampler.Value; -import android.util.Log; - - -public class RsRenderStatesRS { - - int mWidth; - int mHeight; - - public RsRenderStatesRS() { - } - - public void init(RenderScriptGL rs, Resources res) { - mRS = rs; - mWidth = mRS.getWidth(); - mHeight = mRS.getHeight(); - mRes = res; - mOptionsARGB.inScaled = false; - mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888; - mMode = 0; - mMaxModes = 0; - initRS(); - } - - public void surfaceChanged() { - mWidth = mRS.getWidth(); - mHeight = mRS.getHeight(); - - Matrix4f proj = new Matrix4f(); - proj.loadOrthoWindow(mWidth, mHeight); - mPVA.setProjection(proj); - } - - private Resources mRes; - private RenderScriptGL mRS; - - private Sampler mLinearClamp; - private Sampler mLinearWrap; - private Sampler mMipLinearWrap; - private Sampler mNearestClamp; - private Sampler mMipLinearAniso8; - private Sampler mMipLinearAniso15; - - private ProgramStore mProgStoreBlendNoneDepth; - private ProgramStore mProgStoreBlendNone; - private ProgramStore mProgStoreBlendAlpha; - private ProgramStore mProgStoreBlendAdd; - - private ProgramFragment mProgFragmentTexture; - private ProgramFragment mProgFragmentColor; - - private ProgramVertex mProgVertex; - private ProgramVertexFixedFunction.Constants mPVA; - - // Custom shaders - private ProgramVertex mProgVertexCustom; - private ProgramFragment mProgFragmentCustom; - private ProgramFragment mProgFragmentMultitex; - private ScriptField_VertexShaderConstants_s mVSConst; - private ScriptField_VertexShaderConstants2_s mVSConst2; - private ScriptField_FragentShaderConstants_s mFSConst; - private ScriptField_FragentShaderConstants2_s mFSConst2; - - private ProgramVertex mProgVertexCustom2; - private ProgramFragment mProgFragmentCustom2; - - private ProgramVertex mProgVertexCube; - private ProgramFragment mProgFragmentCube; - - private ProgramRaster mCullBack; - private ProgramRaster mCullFront; - private ProgramRaster mCullNone; - - private Allocation mTexTorus; - private Allocation mTexOpaque; - private Allocation mTexTransparent; - private Allocation mTexChecker; - private Allocation mTexCube; - - private Mesh mMbyNMesh; - private Mesh mTorus; - - Font mFontSans; - Font mFontSerif; - Font mFontSerifBold; - Font mFontSerifItalic; - Font mFontSerifBoldItalic; - Font mFontMono; - private Allocation mTextAlloc; - - private ScriptC_rsrenderstates mScript; - - private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options(); - - int mMode; - int mMaxModes; - - public void onActionDown(int x, int y) { - mMode ++; - mMode = mMode % mMaxModes; - mScript.set_gDisplayMode(mMode); - } - - ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) { - ProgramStore.Builder builder = new ProgramStore.Builder(rs); - builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); - builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE); - builder.setDitherEnabled(false); - builder.setDepthMaskEnabled(false); - return builder.create(); - } - - private Mesh getMbyNMesh(float width, float height, int wResolution, int hResolution) { - - Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, - 2, Mesh.TriangleMeshBuilder.TEXTURE_0); - - for (int y = 0; y <= hResolution; y++) { - final float normalizedY = (float)y / hResolution; - final float yOffset = (normalizedY - 0.5f) * height; - for (int x = 0; x <= wResolution; x++) { - float normalizedX = (float)x / wResolution; - float xOffset = (normalizedX - 0.5f) * width; - tmb.setTexture(normalizedX, normalizedY); - tmb.addVertex(xOffset, yOffset); - } - } - - for (int y = 0; y < hResolution; y++) { - final int curY = y * (wResolution + 1); - final int belowY = (y + 1) * (wResolution + 1); - for (int x = 0; x < wResolution; x++) { - int curV = curY + x; - int belowV = belowY + x; - tmb.addTriangle(curV, belowV, curV + 1); - tmb.addTriangle(belowV, belowV + 1, curV + 1); - } - } - - return tmb.create(true); - } - - private void initProgramStore() { - // Use stock the stock program store object - mProgStoreBlendNoneDepth = ProgramStore.BLEND_NONE_DEPTH_TEST(mRS); - mProgStoreBlendNone = ProgramStore.BLEND_NONE_DEPTH_NONE(mRS); - - // Create a custom program store - ProgramStore.Builder builder = new ProgramStore.Builder(mRS); - builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS); - builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, - ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA); - builder.setDitherEnabled(false); - builder.setDepthMaskEnabled(false); - mProgStoreBlendAlpha = builder.create(); - - mProgStoreBlendAdd = BLEND_ADD_DEPTH_NONE(mRS); - - mScript.set_gProgStoreBlendNoneDepth(mProgStoreBlendNoneDepth); - mScript.set_gProgStoreBlendNone(mProgStoreBlendNone); - mScript.set_gProgStoreBlendAlpha(mProgStoreBlendAlpha); - mScript.set_gProgStoreBlendAdd(mProgStoreBlendAdd); - } - - private void initProgramFragment() { - - ProgramFragmentFixedFunction.Builder texBuilder = new ProgramFragmentFixedFunction.Builder(mRS); - texBuilder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, - ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); - mProgFragmentTexture = texBuilder.create(); - mProgFragmentTexture.bindSampler(mLinearClamp, 0); - - ProgramFragmentFixedFunction.Builder colBuilder = new ProgramFragmentFixedFunction.Builder(mRS); - colBuilder.setVaryingColor(false); - mProgFragmentColor = colBuilder.create(); - - mScript.set_gProgFragmentColor(mProgFragmentColor); - mScript.set_gProgFragmentTexture(mProgFragmentTexture); - } - - private void initProgramVertex() { - ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS); - mProgVertex = pvb.create(); - - mPVA = new ProgramVertexFixedFunction.Constants(mRS); - ((ProgramVertexFixedFunction)mProgVertex).bindConstants(mPVA); - Matrix4f proj = new Matrix4f(); - proj.loadOrthoWindow(mWidth, mHeight); - mPVA.setProjection(proj); - - mScript.set_gProgVertex(mProgVertex); - } - - private void initCustomShaders() { - mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1); - mVSConst2 = new ScriptField_VertexShaderConstants2_s(mRS, 1); - mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1); - mFSConst2 = new ScriptField_FragentShaderConstants2_s(mRS, 1); - - mScript.bind_gVSConstants(mVSConst); - mScript.bind_gVSConstants2(mVSConst2); - mScript.bind_gFSConstants(mFSConst); - mScript.bind_gFSConstants2(mFSConst2); - - // Initialize the shader builder - ProgramVertex.Builder pvbCustom = new ProgramVertex.Builder(mRS); - // Specify the resource that contains the shader string - pvbCustom.setShader(mRes, R.raw.shaderv); - // Use a script field to spcify the input layout - pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); - // Define the constant input layout - pvbCustom.addConstant(mVSConst.getAllocation().getType()); - mProgVertexCustom = pvbCustom.create(); - // Bind the source of constant data - mProgVertexCustom.bindConstants(mVSConst.getAllocation(), 0); - - ProgramFragment.Builder pfbCustom = new ProgramFragment.Builder(mRS); - // Specify the resource that contains the shader string - pfbCustom.setShader(mRes, R.raw.shaderf); - //Tell the builder how many textures we have - pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); - // Define the constant input layout - pfbCustom.addConstant(mFSConst.getAllocation().getType()); - mProgFragmentCustom = pfbCustom.create(); - // Bind the source of constant data - mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0); - - pvbCustom = new ProgramVertex.Builder(mRS); - pvbCustom.setShader(mRes, R.raw.shaderarrayv); - pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); - pvbCustom.addConstant(mVSConst2.getAllocation().getType()); - mProgVertexCustom2 = pvbCustom.create(); - mProgVertexCustom2.bindConstants(mVSConst2.getAllocation(), 0); - - pfbCustom = new ProgramFragment.Builder(mRS); - pfbCustom.setShader(mRes, R.raw.shaderarrayf); - pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); - pfbCustom.addConstant(mFSConst2.getAllocation().getType()); - mProgFragmentCustom2 = pfbCustom.create(); - mProgFragmentCustom2.bindConstants(mFSConst2.getAllocation(), 0); - - // Cubemap test shaders - pvbCustom = new ProgramVertex.Builder(mRS); - pvbCustom.setShader(mRes, R.raw.shadercubev); - pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS)); - pvbCustom.addConstant(mVSConst.getAllocation().getType()); - mProgVertexCube = pvbCustom.create(); - mProgVertexCube.bindConstants(mVSConst.getAllocation(), 0); - - pfbCustom = new ProgramFragment.Builder(mRS); - pfbCustom.setShader(mRes, R.raw.shadercubef); - pfbCustom.addTexture(Program.TextureType.TEXTURE_CUBE); - mProgFragmentCube = pfbCustom.create(); - - pfbCustom = new ProgramFragment.Builder(mRS); - pfbCustom.setShader(mRes, R.raw.multitexf); - for (int texCount = 0; texCount < 3; texCount ++) { - pfbCustom.addTexture(Program.TextureType.TEXTURE_2D); - } - mProgFragmentMultitex = pfbCustom.create(); - - mScript.set_gProgVertexCustom(mProgVertexCustom); - mScript.set_gProgFragmentCustom(mProgFragmentCustom); - mScript.set_gProgVertexCustom2(mProgVertexCustom2); - mScript.set_gProgFragmentCustom2(mProgFragmentCustom2); - mScript.set_gProgVertexCube(mProgVertexCube); - mScript.set_gProgFragmentCube(mProgFragmentCube); - mScript.set_gProgFragmentMultitex(mProgFragmentMultitex); - } - - private Allocation loadTextureRGB(int id) { - return Allocation.createFromBitmapResource(mRS, mRes, id, - Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, - Allocation.USAGE_GRAPHICS_TEXTURE); - } - - private Allocation loadTextureARGB(int id) { - Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB); - return Allocation.createFromBitmap(mRS, b, - Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE, - Allocation.USAGE_GRAPHICS_TEXTURE); - } - - private void loadImages() { - mTexTorus = loadTextureRGB(R.drawable.torusmap); - mTexOpaque = loadTextureRGB(R.drawable.data); - mTexTransparent = loadTextureARGB(R.drawable.leaf); - mTexChecker = loadTextureRGB(R.drawable.checker); - Bitmap b = BitmapFactory.decodeResource(mRes, R.drawable.cubemap_test); - mTexCube = Allocation.createCubemapFromBitmap(mRS, b); - - mScript.set_gTexTorus(mTexTorus); - mScript.set_gTexOpaque(mTexOpaque); - mScript.set_gTexTransparent(mTexTransparent); - mScript.set_gTexChecker(mTexChecker); - mScript.set_gTexCube(mTexCube); - } - - private void initFonts() { - // Sans font by family name - mFontSans = Font.create(mRS, mRes, "sans-serif", Font.Style.NORMAL, 8); - mFontSerif = Font.create(mRS, mRes, "serif", Font.Style.NORMAL, 8); - // Create fonts by family and style - mFontSerifBold = Font.create(mRS, mRes, "serif", Font.Style.BOLD, 8); - mFontSerifItalic = Font.create(mRS, mRes, "serif", Font.Style.ITALIC, 8); - mFontSerifBoldItalic = Font.create(mRS, mRes, "serif", Font.Style.BOLD_ITALIC, 8); - mFontMono = Font.create(mRS, mRes, "mono", Font.Style.NORMAL, 8); - - mTextAlloc = Allocation.createFromString(mRS, "String from allocation", Allocation.USAGE_SCRIPT); - - mScript.set_gFontSans(mFontSans); - mScript.set_gFontSerif(mFontSerif); - mScript.set_gFontSerifBold(mFontSerifBold); - mScript.set_gFontSerifItalic(mFontSerifItalic); - mScript.set_gFontSerifBoldItalic(mFontSerifBoldItalic); - mScript.set_gFontMono(mFontMono); - mScript.set_gTextAlloc(mTextAlloc); - } - - private void initMesh() { - mMbyNMesh = getMbyNMesh(256, 256, 10, 10); - mScript.set_gMbyNMesh(mMbyNMesh); - - FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.torus); - FileA3D.IndexEntry entry = model.getIndexEntry(0); - if (entry == null || entry.getEntryType() != FileA3D.EntryType.MESH) { - Log.e("rs", "could not load model"); - } else { - mTorus = (Mesh)entry.getObject(); - mScript.set_gTorusMesh(mTorus); - } - } - - private void initSamplers() { - Sampler.Builder bs = new Sampler.Builder(mRS); - bs.setMinification(Sampler.Value.LINEAR); - bs.setMagnification(Sampler.Value.LINEAR); - bs.setWrapS(Sampler.Value.WRAP); - bs.setWrapT(Sampler.Value.WRAP); - mLinearWrap = bs.create(); - - mLinearClamp = Sampler.CLAMP_LINEAR(mRS); - mNearestClamp = Sampler.CLAMP_NEAREST(mRS); - mMipLinearWrap = Sampler.WRAP_LINEAR_MIP_LINEAR(mRS); - - bs = new Sampler.Builder(mRS); - bs.setMinification(Sampler.Value.LINEAR_MIP_LINEAR); - bs.setMagnification(Sampler.Value.LINEAR); - bs.setWrapS(Sampler.Value.WRAP); - bs.setWrapT(Sampler.Value.WRAP); - bs.setAnisotropy(8.0f); - mMipLinearAniso8 = bs.create(); - bs.setAnisotropy(15.0f); - mMipLinearAniso15 = bs.create(); - - mScript.set_gLinearClamp(mLinearClamp); - mScript.set_gLinearWrap(mLinearWrap); - mScript.set_gMipLinearWrap(mMipLinearWrap); - mScript.set_gMipLinearAniso8(mMipLinearAniso8); - mScript.set_gMipLinearAniso15(mMipLinearAniso15); - mScript.set_gNearestClamp(mNearestClamp); - } - - private void initProgramRaster() { - mCullBack = ProgramRaster.CULL_BACK(mRS); - mCullFront = ProgramRaster.CULL_FRONT(mRS); - mCullNone = ProgramRaster.CULL_NONE(mRS); - - mScript.set_gCullBack(mCullBack); - mScript.set_gCullFront(mCullFront); - mScript.set_gCullNone(mCullNone); - } - - private void initRS() { - - mScript = new ScriptC_rsrenderstates(mRS, mRes, R.raw.rsrenderstates); - - mMaxModes = mScript.get_gMaxModes(); - - initSamplers(); - initProgramStore(); - initProgramFragment(); - initProgramVertex(); - initFonts(); - loadImages(); - initMesh(); - initProgramRaster(); - initCustomShaders(); - - mRS.bindRootScript(mScript); - } -} - - - diff --git a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesView.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesView.java deleted file mode 100644 index 4d339dd33e1c..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesView.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2008 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.samples; - -import android.renderscript.RSSurfaceView; -import android.renderscript.RenderScriptGL; - -import android.content.Context; -import android.view.MotionEvent; -import android.view.SurfaceHolder; - -public class RsRenderStatesView extends RSSurfaceView { - - public RsRenderStatesView(Context context) { - super(context); - ensureRenderScript(); - } - - private RenderScriptGL mRS; - private RsRenderStatesRS mRender; - - private void ensureRenderScript() { - if (mRS == null) { - RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig(); - sc.setDepth(16, 24); - mRS = createRenderScriptGL(sc); - mRender = new RsRenderStatesRS(); - mRender.init(mRS, getResources()); - } - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - ensureRenderScript(); - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - super.surfaceChanged(holder, format, w, h); - mRender.surfaceChanged(); - } - - @Override - protected void onDetachedFromWindow() { - mRender = null; - if (mRS != null) { - mRS = null; - destroyRenderScriptGL(); - } - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - if (ev.getAction() == MotionEvent.ACTION_DOWN) { - mRender.onActionDown((int)ev.getX(), (int)ev.getY()); - return true; - } - - return false; - } -} - - diff --git a/libs/rs/java/Samples/src/com/android/samples/rslist.rs b/libs/rs/java/Samples/src/com/android/samples/rslist.rs deleted file mode 100644 index 52c870a19492..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/rslist.rs +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2009 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. - -#pragma version(1) - -#pragma rs java_package_name(com.android.samples) - -#include "rs_graphics.rsh" - -float gDY; - -rs_font gItalic; - -typedef struct ListAllocs_s { - rs_allocation text; -} ListAllocs; - -ListAllocs *gList; - -void init() { - gDY = 0.0f; -} - -int textPos = 0; - -int root(int launchID) { - - rsgClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - textPos -= (int)gDY*2; - gDY *= 0.95; - - rsgFontColor(0.9f, 0.9f, 0.9f, 1.0f); - rsgBindFont(gItalic); - - rs_allocation listAlloc; - rsSetObject(&listAlloc, rsGetAllocation(gList)); - int allocSize = rsAllocationGetDimX(listAlloc); - - int width = rsgGetWidth(); - int height = rsgGetHeight(); - - int itemHeight = 80; - int currentYPos = itemHeight + textPos; - - for (int i = 0; i < allocSize; i ++) { - if (currentYPos - itemHeight > height) { - break; - } - - if (currentYPos > 0) { - rsgDrawRect(0, currentYPos - 1, width, currentYPos, 0); - rsgDrawText(gList[i].text, 30, currentYPos - 32); - } - currentYPos += itemHeight; - } - - return 10; -} diff --git a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs deleted file mode 100644 index 9019533c8d9b..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs +++ /dev/null @@ -1,680 +0,0 @@ -// Copyright (C) 2009 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. - -#pragma version(1) - -#pragma rs java_package_name(com.android.samples) - -#include "rs_graphics.rsh" -#include "shader_def.rsh" - -const int gMaxModes = 11; - -rs_program_vertex gProgVertex; -rs_program_fragment gProgFragmentColor; -rs_program_fragment gProgFragmentTexture; - -rs_program_store gProgStoreBlendNoneDepth; -rs_program_store gProgStoreBlendNone; -rs_program_store gProgStoreBlendAlpha; -rs_program_store gProgStoreBlendAdd; - -rs_allocation gTexOpaque; -rs_allocation gTexTorus; -rs_allocation gTexTransparent; -rs_allocation gTexChecker; -rs_allocation gTexCube; - -rs_mesh gMbyNMesh; -rs_mesh gTorusMesh; - -rs_font gFontSans; -rs_font gFontSerif; -rs_font gFontSerifBold; -rs_font gFontSerifItalic; -rs_font gFontSerifBoldItalic; -rs_font gFontMono; -rs_allocation gTextAlloc; - -int gDisplayMode; - -rs_sampler gLinearClamp; -rs_sampler gLinearWrap; -rs_sampler gMipLinearWrap; -rs_sampler gMipLinearAniso8; -rs_sampler gMipLinearAniso15; -rs_sampler gNearestClamp; - -rs_program_raster gCullBack; -rs_program_raster gCullFront; -rs_program_raster gCullNone; - -// Custom vertex shader compunents -VertexShaderConstants *gVSConstants; -VertexShaderConstants2 *gVSConstants2; -FragentShaderConstants *gFSConstants; -FragentShaderConstants2 *gFSConstants2; -// Export these out to easily set the inputs to shader -VertexShaderInputs *gVSInputs; -// Custom shaders we use for lighting -rs_program_vertex gProgVertexCustom; -rs_program_fragment gProgFragmentCustom; -rs_program_vertex gProgVertexCustom2; -rs_program_fragment gProgFragmentCustom2; -rs_program_vertex gProgVertexCube; -rs_program_fragment gProgFragmentCube; -rs_program_fragment gProgFragmentMultitex; - -float gDt = 0; - -void init() { -} - -static void displayFontSamples() { - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - int yPos = 100; - rsgBindFont(gFontSans); - rsgDrawText("Sans font sample", 30, yPos); - yPos += 30; - rsgFontColor(0.5f, 0.9f, 0.5f, 1.0f); - rsgBindFont(gFontSerif); - rsgDrawText("Serif font sample", 30, yPos); - yPos += 30; - rsgFontColor(0.7f, 0.7f, 0.7f, 1.0f); - rsgBindFont(gFontSerifBold); - rsgDrawText("Serif Bold font sample", 30, yPos); - yPos += 30; - rsgFontColor(0.5f, 0.5f, 0.9f, 1.0f); - rsgBindFont(gFontSerifItalic); - rsgDrawText("Serif Italic font sample", 30, yPos); - yPos += 30; - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontSerifBoldItalic); - rsgDrawText("Serif Bold Italic font sample", 30, yPos); - yPos += 30; - rsgBindFont(gFontMono); - rsgDrawText("Monospace font sample", 30, yPos); - yPos += 50; - - // Now use text metrics to center the text - uint width = rsgGetWidth(); - uint height = rsgGetHeight(); - int left = 0, right = 0, top = 0, bottom = 0; - - rsgFontColor(0.9f, 0.9f, 0.95f, 1.0f); - rsgBindFont(gFontSerifBoldItalic); - - rsgMeasureText(gTextAlloc, &left, &right, &top, &bottom); - int centeredPos = width / 2 - (right - left) / 2; - rsgDrawText(gTextAlloc, centeredPos, yPos); - yPos += 30; - - const char* text = "Centered Text Sample"; - rsgMeasureText(text, &left, &right, &top, &bottom); - centeredPos = width / 2 - (right - left) / 2; - rsgDrawText(text, centeredPos, yPos); - yPos += 30; - - rsgBindFont(gFontSans); - text = "More Centered Text Samples"; - rsgMeasureText(text, &left, &right, &top, &bottom); - centeredPos = width / 2 - (right - left) / 2; - rsgDrawText(text, centeredPos, yPos); - yPos += 30; - - // Now draw bottom and top right aligned text - text = "Top-right aligned text"; - rsgMeasureText(text, &left, &right, &top, &bottom); - rsgDrawText(text, width - right, top); - - text = "Top-left"; - rsgMeasureText(text, &left, &right, &top, &bottom); - rsgDrawText(text, -left, top); - - text = "Bottom-right aligned text"; - rsgMeasureText(text, &left, &right, &top, &bottom); - rsgDrawText(text, width - right, height + bottom); - -} - -static void bindProgramVertexOrtho() { - // Default vertex sahder - rsgBindProgramVertex(gProgVertex); - // Setup the projectioni matrix - rs_matrix4x4 proj; - rsMatrixLoadOrtho(&proj, 0, rsgGetWidth(), rsgGetHeight(), 0, -500, 500); - rsgProgramVertexLoadProjectionMatrix(&proj); -} - -static void displayShaderSamples() { - bindProgramVertexOrtho(); - rs_matrix4x4 matrix; - rsMatrixLoadIdentity(&matrix); - rsgProgramVertexLoadModelMatrix(&matrix); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNone); - rsgBindProgramFragment(gProgFragmentTexture); - rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); - rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); - - float startX = 0, startY = 0; - float width = 256, height = 256; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1, - startX + width, startY + height, 0, 1, 1, - startX + width, startY, 0, 1, 0); - - startX = 200; startY = 0; - width = 128; height = 128; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1, - startX + width, startY + height, 0, 1, 1, - startX + width, startY, 0, 1, 0); - - rsgBindProgramStore(gProgStoreBlendAlpha); - rsgBindTexture(gProgFragmentTexture, 0, gTexTransparent); - startX = 0; startY = 200; - width = 128; height = 128; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1, - startX + width, startY + height, 0, 1, 1, - startX + width, startY, 0, 1, 0); - - // Fragment program with simple color - rsgBindProgramFragment(gProgFragmentColor); - rsgProgramFragmentConstantColor(gProgFragmentColor, 0.9, 0.3, 0.3, 1); - rsgDrawRect(200, 300, 350, 450, 0); - rsgProgramFragmentConstantColor(gProgFragmentColor, 0.3, 0.9, 0.3, 1); - rsgDrawRect(50, 400, 400, 600, 0); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("Texture shader", 10, 50); - rsgDrawText("Alpha-blended texture shader", 10, 280); - rsgDrawText("Flat color shader", 100, 450); -} - -static void displayBlendingSamples() { - int i; - - bindProgramVertexOrtho(); - rs_matrix4x4 matrix; - rsMatrixLoadIdentity(&matrix); - rsgProgramVertexLoadModelMatrix(&matrix); - - rsgBindProgramFragment(gProgFragmentColor); - - rsgBindProgramStore(gProgStoreBlendNone); - for (i = 0; i < 3; i ++) { - float iPlusOne = (float)(i + 1); - rsgProgramFragmentConstantColor(gProgFragmentColor, - 0.1f*iPlusOne, 0.2f*iPlusOne, 0.3f*iPlusOne, 1); - float yPos = 150 * (float)i; - rsgDrawRect(0, yPos, 200, yPos + 200, 0); - } - - rsgBindProgramStore(gProgStoreBlendAlpha); - for (i = 0; i < 3; i ++) { - float iPlusOne = (float)(i + 1); - rsgProgramFragmentConstantColor(gProgFragmentColor, - 0.2f*iPlusOne, 0.3f*iPlusOne, 0.1f*iPlusOne, 0.5); - float yPos = 150 * (float)i; - rsgDrawRect(150, yPos, 350, yPos + 200, 0); - } - - rsgBindProgramStore(gProgStoreBlendAdd); - for (i = 0; i < 3; i ++) { - float iPlusOne = (float)(i + 1); - rsgProgramFragmentConstantColor(gProgFragmentColor, - 0.3f*iPlusOne, 0.1f*iPlusOne, 0.2f*iPlusOne, 0.5); - float yPos = 150 * (float)i; - rsgDrawRect(300, yPos, 500, yPos + 200, 0); - } - - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("No Blending", 10, 50); - rsgDrawText("Alpha Blending", 160, 150); - rsgDrawText("Additive Blending", 320, 250); - -} - -static void displayMeshSamples() { - - bindProgramVertexOrtho(); - rs_matrix4x4 matrix; - rsMatrixLoadTranslate(&matrix, 128, 128, 0); - rsgProgramVertexLoadModelMatrix(&matrix); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNone); - rsgBindProgramFragment(gProgFragmentTexture); - rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); - rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); - - rsgDrawMesh(gMbyNMesh); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("User gen 10 by 10 grid mesh", 10, 250); -} - -static void displayTextureSamplers() { - - bindProgramVertexOrtho(); - rs_matrix4x4 matrix; - rsMatrixLoadIdentity(&matrix); - rsgProgramVertexLoadModelMatrix(&matrix); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNone); - rsgBindProgramFragment(gProgFragmentTexture); - rsgBindTexture(gProgFragmentTexture, 0, gTexOpaque); - - // Linear clamp - rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); - float startX = 0, startY = 0; - float width = 300, height = 300; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1.1, - startX + width, startY + height, 0, 1.1, 1.1, - startX + width, startY, 0, 1.1, 0); - - // Linear Wrap - rsgBindSampler(gProgFragmentTexture, 0, gLinearWrap); - startX = 0; startY = 300; - width = 300; height = 300; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1.1, - startX + width, startY + height, 0, 1.1, 1.1, - startX + width, startY, 0, 1.1, 0); - - // Nearest - rsgBindSampler(gProgFragmentTexture, 0, gNearestClamp); - startX = 300; startY = 0; - width = 300; height = 300; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1.1, - startX + width, startY + height, 0, 1.1, 1.1, - startX + width, startY, 0, 1.1, 0); - - rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap); - startX = 300; startY = 300; - width = 300; height = 300; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1.5, - startX + width, startY + height, 0, 1.5, 1.5, - startX + width, startY, 0, 1.5, 0); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("Filtering: linear clamp", 10, 290); - rsgDrawText("Filtering: linear wrap", 10, 590); - rsgDrawText("Filtering: nearest clamp", 310, 290); - rsgDrawText("Filtering: miplinear wrap", 310, 590); -} - -static float gTorusRotation = 0; - -static void displayCullingSamples() { - rsgBindProgramVertex(gProgVertex); - // Setup the projectioni matrix with 60 degree field of view - rs_matrix4x4 proj; - float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); - rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); - rsgProgramVertexLoadProjectionMatrix(&proj); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNoneDepth); - rsgBindProgramFragment(gProgFragmentTexture); - rsgBindSampler(gProgFragmentTexture, 0, gLinearClamp); - rsgBindTexture(gProgFragmentTexture, 0, gTexTorus); - - // Aplly a rotation to our mesh - gTorusRotation += 50.0f * gDt; - if (gTorusRotation > 360.0f) { - gTorusRotation -= 360.0f; - } - - rs_matrix4x4 matrix; - // Position our model on the screen - rsMatrixLoadTranslate(&matrix, -2.0f, 0.0f, -10.0f); - rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); - rsgProgramVertexLoadModelMatrix(&matrix); - // Use front face culling - rsgBindProgramRaster(gCullFront); - rsgDrawMesh(gTorusMesh); - - rsMatrixLoadTranslate(&matrix, 2.0f, 0.0f, -10.0f); - rsMatrixRotate(&matrix, gTorusRotation, 1.0f, 0.0f, 0.0f); - rsgProgramVertexLoadModelMatrix(&matrix); - // Use back face culling - rsgBindProgramRaster(gCullBack); - rsgDrawMesh(gTorusMesh); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("Displaying mesh front/back face culling", 10, rsgGetHeight() - 10); -} - -static float gLight0Rotation = 0; -static float gLight1Rotation = 0; - -static void setupCustomShaderLights() { - float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f}; - float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f}; - float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f}; - float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f}; - float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f}; - float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f}; - - gLight0Rotation += 50.0f * gDt; - if (gLight0Rotation > 360.0f) { - gLight0Rotation -= 360.0f; - } - gLight1Rotation -= 50.0f * gDt; - if (gLight1Rotation > 360.0f) { - gLight1Rotation -= 360.0f; - } - - rs_matrix4x4 l0Mat; - rsMatrixLoadRotate(&l0Mat, gLight0Rotation, 1.0f, 0.0f, 0.0f); - light0Pos = rsMatrixMultiply(&l0Mat, light0Pos); - rs_matrix4x4 l1Mat; - rsMatrixLoadRotate(&l1Mat, gLight1Rotation, 0.0f, 0.0f, 1.0f); - light1Pos = rsMatrixMultiply(&l1Mat, light1Pos); - - // Set light 0 properties - gVSConstants->light0_Posision = light0Pos; - gVSConstants->light0_Diffuse = 1.0f; - gVSConstants->light0_Specular = 0.5f; - gVSConstants->light0_CosinePower = 10.0f; - // Set light 1 properties - gVSConstants->light1_Posision = light1Pos; - gVSConstants->light1_Diffuse = 1.0f; - gVSConstants->light1_Specular = 0.7f; - gVSConstants->light1_CosinePower = 25.0f; - rsgAllocationSyncAll(rsGetAllocation(gVSConstants)); - - gVSConstants2->light_Posision[0] = light0Pos; - gVSConstants2->light_Diffuse[0] = 1.0f; - gVSConstants2->light_Specular[0] = 0.5f; - gVSConstants2->light_CosinePower[0] = 10.0f; - gVSConstants2->light_Posision[1] = light1Pos; - gVSConstants2->light_Diffuse[1] = 1.0f; - gVSConstants2->light_Specular[1] = 0.7f; - gVSConstants2->light_CosinePower[1] = 25.0f; - rsgAllocationSyncAll(rsGetAllocation(gVSConstants2)); - - // Update fragmetn shader constants - // Set light 0 colors - gFSConstants->light0_DiffuseColor = light0DiffCol; - gFSConstants->light0_SpecularColor = light0SpecCol; - // Set light 1 colors - gFSConstants->light1_DiffuseColor = light1DiffCol; - gFSConstants->light1_SpecularColor = light1SpecCol; - rsgAllocationSyncAll(rsGetAllocation(gFSConstants)); - - gFSConstants2->light_DiffuseColor[0] = light0DiffCol; - gFSConstants2->light_SpecularColor[0] = light0SpecCol; - // Set light 1 colors - gFSConstants2->light_DiffuseColor[1] = light1DiffCol; - gFSConstants2->light_SpecularColor[1] = light1SpecCol; - rsgAllocationSyncAll(rsGetAllocation(gFSConstants2)); -} - -static void displayCustomShaderSamples() { - - // Update vertex shader constants - // Load model matrix - // Aplly a rotation to our mesh - gTorusRotation += 50.0f * gDt; - if (gTorusRotation > 360.0f) { - gTorusRotation -= 360.0f; - } - - // Position our model on the screen - rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f); - rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f); - rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f); - // Setup the projectioni matrix - float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); - rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f); - setupCustomShaderLights(); - - rsgBindProgramVertex(gProgVertexCustom); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNoneDepth); - rsgBindProgramFragment(gProgFragmentCustom); - rsgBindSampler(gProgFragmentCustom, 0, gLinearClamp); - rsgBindTexture(gProgFragmentCustom, 0, gTexTorus); - - // Use back face culling - rsgBindProgramRaster(gCullBack); - rsgDrawMesh(gTorusMesh); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("Custom shader sample", 10, rsgGetHeight() - 10); -} - -static void displayCustomShaderSamples2() { - - // Update vertex shader constants - // Load model matrix - // Aplly a rotation to our mesh - gTorusRotation += 50.0f * gDt; - if (gTorusRotation > 360.0f) { - gTorusRotation -= 360.0f; - } - - // Position our model on the screen - rsMatrixLoadTranslate(&gVSConstants2->model[1], 0.0f, 0.0f, -10.0f); - rsMatrixLoadIdentity(&gVSConstants2->model[0]); - rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 1.0f, 0.0f, 0.0f); - rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 0.0f, 0.0f, 1.0f); - // Setup the projectioni matrix - float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); - rsMatrixLoadPerspective(&gVSConstants2->proj, 30.0f, aspect, 0.1f, 100.0f); - setupCustomShaderLights(); - - rsgBindProgramVertex(gProgVertexCustom2); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNoneDepth); - rsgBindProgramFragment(gProgFragmentCustom2); - rsgBindSampler(gProgFragmentCustom2, 0, gLinearClamp); - rsgBindTexture(gProgFragmentCustom2, 0, gTexTorus); - - // Use back face culling - rsgBindProgramRaster(gCullBack); - rsgDrawMesh(gTorusMesh); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("Custom shader sample with array uniforms", 10, rsgGetHeight() - 10); -} - -static void displayCubemapShaderSample() { - // Update vertex shader constants - // Load model matrix - // Aplly a rotation to our mesh - gTorusRotation += 50.0f * gDt; - if (gTorusRotation > 360.0f) { - gTorusRotation -= 360.0f; - } - - // Position our model on the screen - // Position our model on the screen - rsMatrixLoadTranslate(&gVSConstants->model, 0.0f, 0.0f, -10.0f); - rsMatrixRotate(&gVSConstants->model, gTorusRotation, 1.0f, 0.0f, 0.0f); - rsMatrixRotate(&gVSConstants->model, gTorusRotation, 0.0f, 0.0f, 1.0f); - // Setup the projectioni matrix - float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); - rsMatrixLoadPerspective(&gVSConstants->proj, 30.0f, aspect, 0.1f, 100.0f); - rsgAllocationSyncAll(rsGetAllocation(gFSConstants)); - - rsgBindProgramVertex(gProgVertexCube); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNoneDepth); - rsgBindProgramFragment(gProgFragmentCube); - rsgBindSampler(gProgFragmentCube, 0, gLinearClamp); - rsgBindTexture(gProgFragmentCube, 0, gTexCube); - - // Use back face culling - rsgBindProgramRaster(gCullBack); - rsgDrawMesh(gTorusMesh); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("Cubemap shader sample", 10, rsgGetHeight() - 10); -} - -static void displayMultitextureSample() { - bindProgramVertexOrtho(); - rs_matrix4x4 matrix; - rsMatrixLoadIdentity(&matrix); - rsgProgramVertexLoadModelMatrix(&matrix); - - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNone); - rsgBindProgramFragment(gProgFragmentMultitex); - rsgBindSampler(gProgFragmentMultitex, 0, gLinearClamp); - rsgBindSampler(gProgFragmentMultitex, 1, gLinearWrap); - rsgBindSampler(gProgFragmentMultitex, 2, gLinearClamp); - rsgBindTexture(gProgFragmentMultitex, 0, gTexChecker); - rsgBindTexture(gProgFragmentMultitex, 1, gTexTorus); - rsgBindTexture(gProgFragmentMultitex, 2, gTexTransparent); - - float startX = 0, startY = 0; - float width = 256, height = 256; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 1, - startX + width, startY + height, 0, 1, 1, - startX + width, startY, 0, 1, 0); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - rsgDrawText("Custom shader with multitexturing", 10, 280); -} - -static float gAnisoTime = 0.0f; -static uint anisoMode = 0; -static void displayAnisoSample() { - - gAnisoTime += gDt; - - rsgBindProgramVertex(gProgVertex); - float aspect = (float)rsgGetWidth() / (float)rsgGetHeight(); - rs_matrix4x4 proj; - rsMatrixLoadPerspective(&proj, 30.0f, aspect, 0.1f, 100.0f); - rsgProgramVertexLoadProjectionMatrix(&proj); - - rs_matrix4x4 matrix; - // Fragment shader with texture - rsgBindProgramStore(gProgStoreBlendNone); - rsgBindProgramFragment(gProgFragmentTexture); - rsMatrixLoadTranslate(&matrix, 0.0f, 0.0f, -10.0f); - rsMatrixRotate(&matrix, -80, 1.0f, 0.0f, 0.0f); - rsgProgramVertexLoadModelMatrix(&matrix); - - rsgBindProgramRaster(gCullNone); - - rsgBindTexture(gProgFragmentTexture, 0, gTexChecker); - - if (gAnisoTime >= 5.0f) { - gAnisoTime = 0.0f; - anisoMode ++; - anisoMode = anisoMode % 3; - } - - if (anisoMode == 0) { - rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso8); - } else if (anisoMode == 1) { - rsgBindSampler(gProgFragmentTexture, 0, gMipLinearAniso15); - } else { - rsgBindSampler(gProgFragmentTexture, 0, gMipLinearWrap); - } - - float startX = -15; - float startY = -15; - float width = 30; - float height = 30; - rsgDrawQuadTexCoords(startX, startY, 0, 0, 0, - startX, startY + height, 0, 0, 10, - startX + width, startY + height, 0, 10, 10, - startX + width, startY, 0, 10, 0); - - rsgBindProgramRaster(gCullBack); - - rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f); - rsgBindFont(gFontMono); - if (anisoMode == 0) { - rsgDrawText("Anisotropic filtering 8", 10, 40); - } else if (anisoMode == 1) { - rsgDrawText("Anisotropic filtering 15", 10, 40); - } else { - rsgDrawText("Miplinear filtering", 10, 40); - } -} - -int root(int launchID) { - - gDt = rsGetDt(); - - rsgClearColor(0.2f, 0.2f, 0.2f, 0.0f); - rsgClearDepth(1.0f); - - switch (gDisplayMode) { - case 0: - displayFontSamples(); - break; - case 1: - displayShaderSamples(); - break; - case 2: - displayBlendingSamples(); - break; - case 3: - displayMeshSamples(); - break; - case 4: - displayTextureSamplers(); - break; - case 5: - displayCullingSamples(); - break; - case 6: - displayCustomShaderSamples(); - break; - case 7: - displayMultitextureSample(); - break; - case 8: - displayAnisoSample(); - break; - case 9: - displayCustomShaderSamples2(); - break; - case 10: - displayCubemapShaderSample(); - break; - } - - return 10; -} diff --git a/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh deleted file mode 100644 index 1d804c693165..000000000000 --- a/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (C) 2009 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. - -#pragma version(1) - -#pragma rs java_package_name(com.android.samples) - -typedef struct VertexShaderConstants_s { - rs_matrix4x4 model; - rs_matrix4x4 proj; - float4 light0_Posision; - float light0_Diffuse; - float light0_Specular; - float light0_CosinePower; - - float4 light1_Posision; - float light1_Diffuse; - float light1_Specular; - float light1_CosinePower; -} VertexShaderConstants; - -typedef struct VertexShaderConstants2_s { - rs_matrix4x4 model[2]; - rs_matrix4x4 proj; - float4 light_Posision[2]; - float light_Diffuse[2]; - float light_Specular[2]; - float light_CosinePower[2]; -} VertexShaderConstants2; - -typedef struct VertexShaderConstants3_s { - rs_matrix4x4 model; - rs_matrix4x4 proj; - float time; -} VertexShaderConstants3; - - -typedef struct FragentShaderConstants_s { - float4 light0_DiffuseColor; - float4 light0_SpecularColor; - - float4 light1_DiffuseColor; - float4 light1_SpecularColor; -} FragentShaderConstants; - -typedef struct FragentShaderConstants2_s { - float4 light_DiffuseColor[2]; - float4 light_SpecularColor[2]; -} FragentShaderConstants2; - -typedef struct FragentShaderConstants3_s { - float4 light0_DiffuseColor; - float4 light0_SpecularColor; - float4 light0_Posision; - float light0_Diffuse; - float light0_Specular; - float light0_CosinePower; - - float4 light1_DiffuseColor; - float4 light1_SpecularColor; - float4 light1_Posision; - float light1_Diffuse; - float light1_Specular; - float light1_CosinePower; -} FragentShaderConstants3; - -typedef struct VertexShaderInputs_s { - float4 position; - float3 normal; - float2 texture0; -} VertexShaderInputs; - diff --git a/libs/rs/java/_index.html b/libs/rs/java/_index.html deleted file mode 100644 index 5872431420e6..000000000000 --- a/libs/rs/java/_index.html +++ /dev/null @@ -1 +0,0 @@ -<p>A set of samples that demonstrate how to use various features of the Renderscript APIs.</p>
\ No newline at end of file diff --git a/libs/surfaceflinger_client/Surface.cpp b/libs/surfaceflinger_client/Surface.cpp index 1e9bd744f51c..68611d6a37e4 100644 --- a/libs/surfaceflinger_client/Surface.cpp +++ b/libs/surfaceflinger_client/Surface.cpp @@ -1040,7 +1040,7 @@ int Surface::getBufferIndex(const sp<GraphicBuffer>& buffer) const // e.g. if GraphicBuffer is used to wrap an android_native_buffer_t that // was dequeued from an ANativeWindow. for (size_t i = 0; i < mBuffers.size(); i++) { - if (buffer->handle == mBuffers[i]->handle) { + if (mBuffers[i] != 0 && buffer->handle == mBuffers[i]->handle) { idx = mBuffers[i]->getIndex(); break; } diff --git a/libs/rs/java/Balls/Android.mk b/libs/usb/Android.mk index 5b656287c56b..d0ef6f0ff379 100644 --- a/libs/rs/java/Balls/Android.mk +++ b/libs/usb/Android.mk @@ -14,18 +14,14 @@ # limitations under the License. # -ifneq ($(TARGET_SIMULATOR),true) - LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) -LOCAL_MODULE_TAGS := optional +include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src) -#LOCAL_STATIC_JAVA_LIBRARIES := android.renderscript +LOCAL_SRC_FILES := $(call all-java-files-under,src) -LOCAL_PACKAGE_NAME := Balls +LOCAL_MODULE_TAGS := optional -include $(BUILD_PACKAGE) +LOCAL_MODULE:= com.google.android.usb -endif +include $(BUILD_JAVA_LIBRARY) diff --git a/libs/usb/src/com/google/android/usb/UsbAccessory.java b/libs/usb/src/com/google/android/usb/UsbAccessory.java new file mode 100644 index 000000000000..91095f3f3b21 --- /dev/null +++ b/libs/usb/src/com/google/android/usb/UsbAccessory.java @@ -0,0 +1,96 @@ +/* + * 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.google.android.usb; + +/** + * A class representing a USB accessory. + */ +public final class UsbAccessory { + + private final String mManufacturer; + private final String mModel; + private final String mType; + private final String mVersion; + + /* package */ UsbAccessory(android.hardware.UsbAccessory accessory) { + mManufacturer = accessory.getManufacturer(); + mModel = accessory.getModel(); + mType = accessory.getType(); + mVersion = accessory.getVersion(); + } + + /** + * Returns the manufacturer of the accessory. + * + * @return the accessory manufacturer + */ + public String getManufacturer() { + return mManufacturer; + } + + /** + * Returns the model name of the accessory. + * + * @return the accessory model + */ + public String getModel() { + return mModel; + } + + /** + * Returns the type of the accessory. + * + * @return the accessory type + */ + public String getType() { + return mType; + } + + /** + * Returns the version of the accessory. + * + * @return the accessory version + */ + public String getVersion() { + return mVersion; + } + + private static boolean compare(String s1, String s2) { + if (s1 == null) return (s2 == null); + return s1.equals(s2); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof UsbAccessory) { + UsbAccessory accessory = (UsbAccessory)obj; + return (compare(mManufacturer, accessory.getManufacturer()) && + compare(mModel, accessory.getModel()) && + compare(mType, accessory.getType()) && + compare(mVersion, accessory.getVersion())); + } + return false; + } + + @Override + public String toString() { + return "UsbAccessory[mManufacturer=" + mManufacturer + + ", mModel=" + mModel + + ", mType=" + mType + + ", mVersion=" + mVersion + "]"; + } +} diff --git a/libs/usb/src/com/google/android/usb/UsbManager.java b/libs/usb/src/com/google/android/usb/UsbManager.java new file mode 100644 index 000000000000..1b9bff9173c8 --- /dev/null +++ b/libs/usb/src/com/google/android/usb/UsbManager.java @@ -0,0 +1,127 @@ +/* + * 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.google.android.usb; + +import android.content.Context; +import android.content.Intent; +import android.hardware.IUsbManager; +import android.os.IBinder; +import android.os.ParcelFileDescriptor; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +/** + * This class allows you to access the state of USB, both in host and device mode. + * + * <p>You can obtain an instance of this class by calling {@link #getInstance} + * + */ +public class UsbManager { + private static final String TAG = "UsbManager"; + + /** + * Broadcast Action: A broadcast for USB accessory attached event. + * + * This intent is sent when a USB accessory is attached. + * Call {@link #getAccessory(android.content.Intent)} to retrieve the + * {@link com.google.android.usb.UsbAccessory} for the attached accessory. + */ + public static final String ACTION_USB_ACCESSORY_ATTACHED = + "android.hardware.action.USB_ACCESSORY_ATTACHED"; + + /** + * Broadcast Action: A broadcast for USB accessory detached event. + * + * This intent is sent when a USB accessory is detached. + * Call {@link #getAccessory(android.content.Intent)} to retrieve the + * {@link com.google.android.usb.UsbAccessory} for the attached accessory that was detached. + */ + public static final String ACTION_USB_ACCESSORY_DETACHED = + "android.hardware.action.USB_ACCESSORY_DETACHED"; + + private final IUsbManager mService; + + private UsbManager(IUsbManager service) { + mService = service; + } + + /** + * Returns a new instance of this class. + * + * @return UsbManager instance. + */ + public static UsbManager getInstance() { + IBinder b = ServiceManager.getService(Context.USB_SERVICE); + return new UsbManager(IUsbManager.Stub.asInterface(b)); + } + + /** + * Returns the {@link com.google.android.usb.UsbAccessory} for + * a {@link #ACTION_USB_ACCESSORY_ATTACHED} or {@link #ACTION_USB_ACCESSORY_ATTACHED} + * broadcast Intent + * + * @return UsbAccessory for the broadcast. + */ + public static UsbAccessory getAccessory(Intent intent) { + android.hardware.UsbAccessory accessory = + intent.getParcelableExtra(android.hardware.UsbManager.EXTRA_ACCESSORY); + if (accessory == null) { + return null; + } else { + return new UsbAccessory(accessory); + } + } + + /** + * Returns a list of currently attached USB accessories. + * (in the current implementation there can be at most one) + * + * @return list of USB accessories, or null if none are attached. + */ + public UsbAccessory[] getAccessoryList() { + try { + android.hardware.UsbAccessory accessory = mService.getCurrentAccessory(); + if (accessory == null) { + return null; + } else { + return new UsbAccessory[] { new UsbAccessory(accessory) }; + } + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in getAccessoryList" , e); + return null; + } + } + + /** + * Opens a file descriptor for reading and writing data to the USB accessory. + * + * @param accessory the USB accessory to open + * @return file descriptor, or null if the accessor could not be opened. + */ + public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { + try { + return mService.openAccessory(new android.hardware.UsbAccessory( + accessory.getManufacturer(),accessory.getModel(), + accessory.getType(), accessory.getVersion())); + } catch (RemoteException e) { + Log.e(TAG, "RemoteException in openAccessory" , e); + return null; + } + } +} diff --git a/libs/usb/tests/AccessoryChat/Android.mk b/libs/usb/tests/AccessoryChat/Android.mk new file mode 100644 index 000000000000..b8545693b3d2 --- /dev/null +++ b/libs/usb/tests/AccessoryChat/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := tests + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_PACKAGE_NAME := AccessoryChatGB + +LOCAL_JAVA_LIBRARIES := com.google.android.usb + +# Force an old SDK version to make sure we aren't using newer UsbManager APIs +LOCAL_SDK_VERSION := 8 + +include $(BUILD_PACKAGE) diff --git a/libs/usb/tests/AccessoryChat/AndroidManifest.xml b/libs/usb/tests/AccessoryChat/AndroidManifest.xml new file mode 100644 index 000000000000..b63999c5200e --- /dev/null +++ b/libs/usb/tests/AccessoryChat/AndroidManifest.xml @@ -0,0 +1,23 @@ +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.google.android.accessorychat"> + + <application> + <uses-library android:name="com.google.android.usb" /> + + <activity android:name="AccessoryChat" android:label="Accessory Chat GB"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.DEFAULT" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + + <intent-filter> + <action android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" /> + </intent-filter> + + <meta-data android:name="android.hardware.action.USB_ACCESSORY_ATTACHED" + android:resource="@xml/accessory_filter" /> + </activity> + </application> + <uses-sdk android:minSdkVersion="8" /> +</manifest> diff --git a/libs/usb/tests/AccessoryChat/README.txt b/libs/usb/tests/AccessoryChat/README.txt new file mode 100644 index 000000000000..d2ce11ea9f2e --- /dev/null +++ b/libs/usb/tests/AccessoryChat/README.txt @@ -0,0 +1,10 @@ +This is a test app for the USB accessory APIs. It consists of two parts: + +AccessoryChat - A Java app with a chat-like UI that sends and receives strings + via the UsbAccessory class. + +accessorychat - A C command-line program that communicates with AccessoryChat. + This program behaves as if it were a USB accessory. + It builds both for the host (Linux PC) and as an android + command line program, which will work if run as root on an + android device with USB host support diff --git a/libs/usb/tests/AccessoryChat/accessorychat/Android.mk b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk new file mode 100644 index 000000000000..300224a016d4 --- /dev/null +++ b/libs/usb/tests/AccessoryChat/accessorychat/Android.mk @@ -0,0 +1,34 @@ +LOCAL_PATH:= $(call my-dir) + +# Build for Linux (desktop) host +ifeq ($(HOST_OS),linux) + +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := accessorychat.c + +LOCAL_MODULE := accessorychat + +LOCAL_C_INCLUDES += bionic/libc/kernel/common +LOCAL_STATIC_LIBRARIES := libusbhost libcutils +LOCAL_LDLIBS += -lpthread +LOCAL_CFLAGS := -g -O0 + +include $(BUILD_HOST_EXECUTABLE) + +endif + +# Build for device +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := accessorychat.c + +LOCAL_MODULE := accessorychat + +LOCAL_SHARED_LIBRARIES := libusbhost libcutils + +include $(BUILD_EXECUTABLE) diff --git a/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c new file mode 100644 index 000000000000..94cc0ce7f498 --- /dev/null +++ b/libs/usb/tests/AccessoryChat/accessorychat/accessorychat.c @@ -0,0 +1,174 @@ +/* + * 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. + */ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <pthread.h> + +#include <usbhost/usbhost.h> +#include <linux/usb/f_accessory.h> + +struct usb_device *sDevice = NULL; + +static void* read_thread(void* arg) { + int endpoint = (int)arg; + int ret = 0; + + while (sDevice && ret >= 0) { + char buffer[16384]; + + ret = usb_device_bulk_transfer(sDevice, endpoint, buffer, sizeof(buffer), 1000); + if (ret < 0 && errno == ETIMEDOUT) + ret = 0; + if (ret > 0) { + fwrite(buffer, 1, ret, stdout); + printf("\n"); + fflush(stdout); + } + } + + return NULL; +} + +static void* write_thread(void* arg) { + int endpoint = (int)arg; + int ret = 0; + + while (ret >= 0) { + char buffer[16384]; + char *line = fgets(buffer, sizeof(buffer), stdin); + if (!line || !sDevice) + break; + ret = usb_device_bulk_transfer(sDevice, endpoint, line, strlen(line), 1000); + } + + return NULL; +} + +static void send_string(struct usb_device *device, int index, const char* string) { + int ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR, + ACCESSORY_SEND_STRING, 0, index, (void *)string, strlen(string) + 1, 0); +} + +static int usb_device_added(const char *devname, void* client_data) { + struct usb_descriptor_header* desc; + struct usb_descriptor_iter iter; + uint16_t vendorId, productId; + int ret; + pthread_t th; + + struct usb_device *device = usb_device_open(devname); + if (!device) { + fprintf(stderr, "usb_device_open failed\n"); + return 0; + } + + vendorId = usb_device_get_vendor_id(device); + productId = usb_device_get_product_id(device); + + if (vendorId == 0x18D1 || vendorId == 0x22B8) { + if (!sDevice && (productId == 0x2D00 || productId == 0x2D01)) { + struct usb_descriptor_header* desc; + struct usb_descriptor_iter iter; + struct usb_interface_descriptor *intf = NULL; + struct usb_endpoint_descriptor *ep1 = NULL; + struct usb_endpoint_descriptor *ep2 = NULL; + + printf("Found android device in accessory mode\n"); + sDevice = device; + + usb_descriptor_iter_init(device, &iter); + while ((desc = usb_descriptor_iter_next(&iter)) != NULL && (!intf || !ep1 || !ep2)) { + if (desc->bDescriptorType == USB_DT_INTERFACE) { + intf = (struct usb_interface_descriptor *)desc; + } else if (desc->bDescriptorType == USB_DT_ENDPOINT) { + if (ep1) + ep2 = (struct usb_endpoint_descriptor *)desc; + else + ep1 = (struct usb_endpoint_descriptor *)desc; + } + } + + if (!intf) { + fprintf(stderr, "interface not found\n"); + exit(1); + } + if (!ep1 || !ep2) { + fprintf(stderr, "endpoints not found\n"); + exit(1); + } + + if (usb_device_claim_interface(device, intf->bInterfaceNumber)) { + fprintf(stderr, "usb_device_claim_interface failed errno: %d\n", errno); + exit(1); + } + + if ((ep1->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) { + pthread_create(&th, NULL, read_thread, (void *)ep1->bEndpointAddress); + pthread_create(&th, NULL, write_thread, (void *)ep2->bEndpointAddress); + } else { + pthread_create(&th, NULL, read_thread, (void *)ep2->bEndpointAddress); + pthread_create(&th, NULL, write_thread, (void *)ep1->bEndpointAddress); + } + } else { + printf("Found possible android device - attempting to switch to accessory mode\n"); + + send_string(device, ACCESSORY_STRING_MANUFACTURER, "Google, Inc."); + send_string(device, ACCESSORY_STRING_MODEL, "AccessoryChat"); + send_string(device, ACCESSORY_STRING_TYPE, "Sample Program"); + send_string(device, ACCESSORY_STRING_VERSION, "1.0"); + + ret = usb_device_control_transfer(device, USB_DIR_OUT | USB_TYPE_VENDOR, + ACCESSORY_START, 0, 0, 0, 0, 0); + return 0; + } + } + + if (device != sDevice) + usb_device_close(device); + + return 0; +} + +static int usb_device_removed(const char *devname, void* client_data) { + if (sDevice && !strcmp(usb_device_get_name(sDevice), devname)) { + usb_device_close(sDevice); + sDevice = NULL; + // exit when we are disconnected + return 1; + } + return 0; +} + + +int main(int argc, char* argv[]) { + struct usb_host_context* context = usb_host_init(); + if (!context) { + fprintf(stderr, "usb_host_init failed"); + return 1; + } + + // this will never return so it is safe to pass thiz directly + usb_host_run(context, usb_device_added, usb_device_removed, NULL, NULL); + return 0; +} diff --git a/libs/usb/tests/AccessoryChat/res/layout/accessory_chat.xml b/libs/usb/tests/AccessoryChat/res/layout/accessory_chat.xml new file mode 100644 index 000000000000..596ecbf756c8 --- /dev/null +++ b/libs/usb/tests/AccessoryChat/res/layout/accessory_chat.xml @@ -0,0 +1,47 @@ +<?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:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" + > + + <ScrollView android:id="@+id/scroll" + android:layout_width="match_parent" + android:layout_height="0px" + android:layout_weight="1" + > + <TextView android:id="@+id/log" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="25dp" + android:textSize="12sp" + android:textColor="#ffffffff" + /> + </ScrollView> + + <EditText android:id="@+id/message" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:capitalize="sentences" + android:autoText="true" + android:singleLine="true" + /> + +</LinearLayout> + + diff --git a/libs/usb/tests/AccessoryChat/res/xml/accessory_filter.xml b/libs/usb/tests/AccessoryChat/res/xml/accessory_filter.xml new file mode 100644 index 000000000000..588946f58617 --- /dev/null +++ b/libs/usb/tests/AccessoryChat/res/xml/accessory_filter.xml @@ -0,0 +1,18 @@ +<?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> + <usb-accessory manufacturer="Google, Inc." model="AccessoryChat" type="Sample Program" version="1.0" /> +</resources> diff --git a/libs/usb/tests/AccessoryChat/src/com/google/android/accessorychat/AccessoryChat.java b/libs/usb/tests/AccessoryChat/src/com/google/android/accessorychat/AccessoryChat.java new file mode 100644 index 000000000000..0a5701cf9006 --- /dev/null +++ b/libs/usb/tests/AccessoryChat/src/com/google/android/accessorychat/AccessoryChat.java @@ -0,0 +1,153 @@ +/* + * 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.google.android.accessorychat; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.Handler; +import android.os.Message; +import android.os.ParcelFileDescriptor; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.util.Log; +import android.widget.EditText; +import android.widget.TextView; + +import com.google.android.usb.UsbAccessory; +import com.google.android.usb.UsbManager; + +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +public class AccessoryChat extends Activity implements Runnable, TextView.OnEditorActionListener { + + private static final String TAG = "AccessoryChat"; + TextView mLog; + EditText mEditText; + ParcelFileDescriptor mFileDescriptor; + FileInputStream mInputStream; + FileOutputStream mOutputStream; + + private static final int MESSAGE_LOG = 1; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.accessory_chat); + mLog = (TextView)findViewById(R.id.log); + mEditText = (EditText)findViewById(R.id.message); + mEditText.setOnEditorActionListener(this); + } + + @Override + public void onResume() { + super.onResume(); + + Intent intent = getIntent(); + Log.d(TAG, "intent: " + intent); + UsbManager manager = UsbManager.getInstance(); + UsbAccessory[] accessories = manager.getAccessoryList(); + UsbAccessory accessory = (accessories == null ? null : accessories[0]); + if (accessory != null) { + mFileDescriptor = manager.openAccessory(accessory); + if (mFileDescriptor != null) { + FileDescriptor fd = mFileDescriptor.getFileDescriptor(); + mInputStream = new FileInputStream(fd); + mOutputStream = new FileOutputStream(fd); + Thread thread = new Thread(null, this, "AccessoryChat"); + thread.start(); + } else { + Log.d(TAG, "openAccessory fail"); + } + } else { + Log.d(TAG, "mAccessory is null"); + } + } + + @Override + public void onPause() { + super.onPause(); + if (mFileDescriptor != null) { + try { + mFileDescriptor.close(); + } catch (IOException e) { + } finally { + mFileDescriptor = null; + } + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE && mOutputStream != null) { + try { + mOutputStream.write(v.getText().toString().getBytes()); + } catch (IOException e) { + Log.e(TAG, "write failed", e); + } + v.setText(""); + return true; + } + Log.d(TAG, "onEditorAction " + actionId + " event: " + event); + return false; + } + + public void run() { + int ret = 0; + byte[] buffer = new byte[16384]; + while (ret >= 0) { + try { + ret = mInputStream.read(buffer); + } catch (IOException e) { + break; + } + + if (ret > 0) { + Message m = Message.obtain(mHandler, MESSAGE_LOG); + String text = new String(buffer, 0, ret); + Log.d(TAG, "chat: " + text); + m.obj = text; + mHandler.sendMessage(m); + } + } + Log.d(TAG, "thread out"); + } + + Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_LOG: + mLog.setText(mLog.getText() + "\n" + (String)msg.obj); + break; + } + } + }; +} + + diff --git a/libs/utils/RefBase.cpp b/libs/utils/RefBase.cpp index 0fd404d66c1e..bb6c1255f38a 100644 --- a/libs/utils/RefBase.cpp +++ b/libs/utils/RefBase.cpp @@ -99,20 +99,38 @@ public: #if DEBUG_REFS_FATAL_SANITY_CHECKS LOG_ALWAYS_FATAL("Strong references remain!"); #else - LOGE("Strong references remain!"); + LOGE("Strong references remain:"); #endif + ref_entry* refs = mStrongRefs; + while (refs) { + char inc = refs->ref >= 0 ? '+' : '-'; + LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); +#if DEBUG_REFS_CALLSTACK_ENABLED + refs->stack.dump(); +#endif; + refs = refs->next; + } } if (!mRetain && mWeakRefs != NULL) { dumpStack = true; #if DEBUG_REFS_FATAL_SANITY_CHECKS - LOG_ALWAYS_FATAL("Weak references remain!"); + LOG_ALWAYS_FATAL("Weak references remain:"); #else LOGE("Weak references remain!"); #endif + ref_entry* refs = mWeakRefs; + while (refs) { + char inc = refs->ref >= 0 ? '+' : '-'; + LOGD("\t%c ID %p (ref %d):", inc, refs->id, refs->ref); +#if DEBUG_REFS_CALLSTACK_ENABLED + refs->stack.dump(); +#endif; + refs = refs->next; + } } - if (dumpStack) { + LOGE("above errors at:"); CallStack stack; stack.update(); stack.dump(); @@ -228,7 +246,8 @@ private: if (mTrackEnabled) { AutoMutex _l(mMutex); - ref_entry* ref = *refs; + ref_entry* const head = *refs; + ref_entry* ref = head; while (ref != NULL) { if (ref->id == id) { *refs = ref->next; @@ -249,6 +268,13 @@ private: "(weakref_type %p) that doesn't exist!", id, mBase, this); + ref = head; + while (ref) { + char inc = ref->ref >= 0 ? '+' : '-'; + LOGD("\t%c ID %p (ref %d):", inc, ref->id, ref->ref); + ref = ref->next; + } + CallStack stack; stack.update(); stack.dump(); diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java index d539833b68a8..ffc3346da993 100755 --- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java +++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java @@ -29,6 +29,7 @@ import android.os.RemoteException; import android.util.Log; import com.android.internal.R; +import com.android.internal.telephony.GsmAlphabet; /** * A GPS Network-initiated Handler class used by LocationManager. @@ -288,58 +289,32 @@ public class GpsNetInitiatedHandler { */ static String decodeGSMPackedString(byte[] input) { - final char CHAR_CR = 0x0D; - int nStridx = 0; - int nPckidx = 0; - int num_bytes = input.length; - int cPrev = 0; - int cCurr = 0; - byte nShift; - byte nextChar; - byte[] stringBuf = new byte[input.length * 2]; - String result = ""; - - while(nPckidx < num_bytes) - { - nShift = (byte) (nStridx & 0x07); - cCurr = input[nPckidx++]; - if (cCurr < 0) cCurr += 256; - - /* A 7-bit character can be split at the most between two bytes of packed - ** data. - */ - nextChar = (byte) (( (cCurr << nShift) | (cPrev >> (8-nShift)) ) & 0x7F); - stringBuf[nStridx++] = nextChar; - - /* Special case where the whole of the next 7-bit character fits inside - ** the current byte of packed data. - */ - if(nShift == 6) - { - /* If the next 7-bit character is a CR (0x0D) and it is the last - ** character, then it indicates a padding character. Drop it. - */ - if (nPckidx == num_bytes || (cCurr >> 1) == CHAR_CR) - { - break; + final char PADDING_CHAR = 0x00; + int lengthBytes = input.length; + int lengthSeptets = (lengthBytes * 8) / 7; + String decoded; + + /* Special case where the last 7 bits in the last byte could hold a valid + * 7-bit character or a padding character. Drop the last 7-bit character + * if it is a padding character. + */ + if (lengthBytes % 7 == 0) { + if (lengthBytes > 0) { + if ((input[lengthBytes - 1] >> 1) == PADDING_CHAR) { + lengthSeptets = lengthSeptets - 1; } - - nextChar = (byte) (cCurr >> 1); - stringBuf[nStridx++] = nextChar; } - - cPrev = cCurr; } - try { - result = new String(stringBuf, 0, nStridx, "US-ASCII"); - } - catch (UnsupportedEncodingException e) - { - Log.e(TAG, e.getMessage()); + decoded = GsmAlphabet.gsm7BitPackedToString(input, 0, lengthSeptets); + + // Return "" if decoding of GSM packed string fails + if (null == decoded) { + Log.e(TAG, "Decoding of GSM packed string failed"); + decoded = ""; } - return result; + return decoded; } static String decodeUTF8String(byte[] input) diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java index 1fe3ccc2c83c..5a73d2d4659a 100644 --- a/media/java/android/media/AudioService.java +++ b/media/java/android/media/AudioService.java @@ -1218,7 +1218,7 @@ public class AudioService extends IAudioService.Stub { if (!checkAudioSettingsPermission("startBluetoothSco()")) { return; } - ScoClient client = getScoClient(cb); + ScoClient client = getScoClient(cb, true); client.incCount(); } @@ -1227,8 +1227,10 @@ public class AudioService extends IAudioService.Stub { if (!checkAudioSettingsPermission("stopBluetoothSco()")) { return; } - ScoClient client = getScoClient(cb); - client.decCount(); + ScoClient client = getScoClient(cb, false); + if (client != null) { + client.decCount(); + } } private class ScoClient implements IBinder.DeathRecipient { @@ -1355,27 +1357,38 @@ public class AudioService extends IAudioService.Stub { } } - public ScoClient getScoClient(IBinder cb) { + private ScoClient getScoClient(IBinder cb, boolean create) { synchronized(mScoClients) { - ScoClient client; + ScoClient client = null; int size = mScoClients.size(); for (int i = 0; i < size; i++) { client = mScoClients.get(i); if (client.getBinder() == cb) return client; } - client = new ScoClient(cb); - mScoClients.add(client); + if (create) { + client = new ScoClient(cb); + mScoClients.add(client); + } return client; } } public void clearAllScoClients(IBinder exceptBinder, boolean stopSco) { synchronized(mScoClients) { + ScoClient savedClient = null; int size = mScoClients.size(); for (int i = 0; i < size; i++) { - if (mScoClients.get(i).getBinder() != exceptBinder) - mScoClients.get(i).clearCount(stopSco); + ScoClient cl = mScoClients.get(i); + if (cl.getBinder() != exceptBinder) { + cl.clearCount(stopSco); + } else { + savedClient = cl; + } + } + mScoClients.clear(); + if (savedClient != null) { + mScoClients.add(savedClient); } } } @@ -2320,6 +2333,7 @@ public class AudioService extends IAudioService.Stub { case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: audioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; mScoAudioState = SCO_STATE_INACTIVE; + clearAllScoClients(null, false); break; case BluetoothHeadset.STATE_AUDIO_CONNECTING: if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL) { diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java index e0df257eca55..53bbb0ff5531 100644 --- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java +++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java @@ -3556,7 +3556,7 @@ class MediaArtistNativeHelper { case MediaProperties.ASPECT_RATIO_4_3: if (height == MediaProperties.HEIGHT_480) retValue = VideoFrameSize.VGA; - if (height == MediaProperties.HEIGHT_720) + else if (height == MediaProperties.HEIGHT_720) retValue = VideoFrameSize.S720p; break; case MediaProperties.ASPECT_RATIO_5_3: @@ -3566,6 +3566,8 @@ class MediaArtistNativeHelper { case MediaProperties.ASPECT_RATIO_11_9: if (height == MediaProperties.HEIGHT_144) retValue = VideoFrameSize.QCIF; + else if (height == MediaProperties.HEIGHT_288) + retValue = VideoFrameSize.CIF; break; } if (retValue == VideoFrameSize.SIZE_UNDEFINED) { diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java index 0b7ec081cca3..022580779c37 100755 --- a/media/java/android/media/videoeditor/MediaProperties.java +++ b/media/java/android/media/videoeditor/MediaProperties.java @@ -29,6 +29,7 @@ public class MediaProperties { * Supported heights */ public static final int HEIGHT_144 = 144; + public static final int HEIGHT_288 = 288; public static final int HEIGHT_360 = 360; public static final int HEIGHT_480 = 480; public static final int HEIGHT_720 = 720; @@ -82,7 +83,8 @@ public class MediaProperties { @SuppressWarnings({"unchecked"}) private static final Pair<Integer, Integer>[] ASPECT_RATIO_11_9_RESOLUTIONS = new Pair[] { - new Pair<Integer, Integer>(176, HEIGHT_144) + new Pair<Integer, Integer>(176, HEIGHT_144), + new Pair<Integer, Integer>(352, HEIGHT_288) }; @SuppressWarnings({"unchecked"}) diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java index a6b454432c09..7e1f73aa88fc 100755 --- a/media/java/android/media/videoeditor/VideoEditorImpl.java +++ b/media/java/android/media/videoeditor/VideoEditorImpl.java @@ -42,6 +42,9 @@ import android.util.Log; import android.util.Xml; import android.view.Surface; import android.view.SurfaceHolder; +import android.os.Debug; +import android.os.SystemProperties; +import android.os.Environment; /** * The VideoEditor implementation {@hide} @@ -134,6 +137,7 @@ public class VideoEditorImpl implements VideoEditor { */ private MediaArtistNativeHelper mMANativeHelper; private boolean mPreviewInProgress = false; + private final boolean mMallocDebug; /** * Constructor @@ -142,6 +146,18 @@ public class VideoEditorImpl implements VideoEditor { * related to the project */ public VideoEditorImpl(String projectPath) throws IOException { + String s; + s = SystemProperties.get("libc.debug.malloc"); + if (s.equals("1")) { + mMallocDebug = true; + try { + dumpHeap("HeapAtStart"); + } catch (Exception ex) { + Log.e(TAG, "dumpHeap returned error in constructor"); + } + } else { + mMallocDebug = false; + } mLock = new Semaphore(1, true); mMANativeHelper = new MediaArtistNativeHelper(projectPath, mLock, this); mProjectPath = projectPath; @@ -373,6 +389,8 @@ public class VideoEditorImpl implements VideoEditor { switch (height) { case MediaProperties.HEIGHT_144: break; + case MediaProperties.HEIGHT_288: + break; case MediaProperties.HEIGHT_360: break; case MediaProperties.HEIGHT_480: @@ -709,6 +727,13 @@ public class VideoEditorImpl implements VideoEditor { unlock(); } } + if (mMallocDebug) { + try { + dumpHeap("HeapAtEnd"); + } catch (Exception ex) { + Log.e(TAG, "dumpHeap returned error in release"); + } + } } /* @@ -1885,4 +1910,32 @@ public class VideoEditorImpl implements VideoEditor { } mLock.release(); } + + /** + * Dumps the heap memory usage information to file + */ + private static void dumpHeap (String filename) throws Exception { + /* Cleanup as much as possible before dump + */ + System.gc(); + System.runFinalization(); + Thread.sleep(1000); + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state)) { + String extDir = + Environment.getExternalStorageDirectory().toString(); + + /* If dump file already exists, then delete it first + */ + if ((new File(extDir + "/" + filename + ".dump")).exists()) { + (new File(extDir + "/" + filename + ".dump")).delete(); + } + /* Dump native heap + */ + FileOutputStream ost = + new FileOutputStream(extDir + "/" + filename + ".dump"); + Debug.dumpNativeHeap(ost.getFD()); + ost.close(); + } + } } diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp index 23081f868fcb..9fe026661b33 100755 --- a/media/jni/mediaeditor/VideoEditorMain.cpp +++ b/media/jni/mediaeditor/VideoEditorMain.cpp @@ -1707,12 +1707,19 @@ videoEditor_populateSettings( if (aFramingCtx->FramingYuv != M4OSA_NULL ) { - if (aFramingCtx->FramingYuv->pac_data != M4OSA_NULL) { - M4OSA_free((M4OSA_MemAddr32)aFramingCtx->FramingYuv->pac_data); - aFramingCtx->FramingYuv->pac_data = M4OSA_NULL; + if (aFramingCtx->FramingYuv[0].pac_data != M4OSA_NULL) { + M4OSA_free((M4OSA_MemAddr32)aFramingCtx->FramingYuv[0].pac_data); + aFramingCtx->FramingYuv[0].pac_data = M4OSA_NULL; } - } - if (aFramingCtx->FramingYuv != M4OSA_NULL) { + if (aFramingCtx->FramingYuv[1].pac_data != M4OSA_NULL) { + M4OSA_free((M4OSA_MemAddr32)aFramingCtx->FramingYuv[1].pac_data); + aFramingCtx->FramingYuv[1].pac_data = M4OSA_NULL; + } + if (aFramingCtx->FramingYuv[2].pac_data != M4OSA_NULL) { + M4OSA_free((M4OSA_MemAddr32)aFramingCtx->FramingYuv[2].pac_data); + aFramingCtx->FramingYuv[2].pac_data = M4OSA_NULL; + } + M4OSA_free((M4OSA_MemAddr32)aFramingCtx->FramingYuv); aFramingCtx->FramingYuv = M4OSA_NULL; } diff --git a/media/libstagefright/DRMExtractor.cpp b/media/libstagefright/DRMExtractor.cpp index 647cf438e007..2809df50bf9b 100644 --- a/media/libstagefright/DRMExtractor.cpp +++ b/media/libstagefright/DRMExtractor.cpp @@ -243,6 +243,7 @@ DRMExtractor::DRMExtractor(const sp<DataSource> &source, const char* mime) mDrmManagerClient(NULL) { mOriginalExtractor = MediaExtractor::Create(source, mime); mOriginalExtractor->setDrmFlag(true); + mOriginalExtractor->getMetaData()->setInt32(kKeyIsDRM, 1); source->getDrmInfo(&mDecryptHandle, &mDrmManagerClient); } diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp index d4651c47d95f..23bad5bb3d68 100644 --- a/media/libstagefright/MediaExtractor.cpp +++ b/media/libstagefright/MediaExtractor.cpp @@ -67,6 +67,7 @@ sp<MediaExtractor> MediaExtractor::Create( mime, confidence); } + bool isDrm = false; // DRM MIME type syntax is "drm+type+original" where // type is "es_based" or "container_based" and // original is the content's cleartext MIME type @@ -78,39 +79,45 @@ sp<MediaExtractor> MediaExtractor::Create( } ++originalMime; if (!strncmp(mime, "drm+es_based+", 13)) { + // DRMExtractor sets container metadata kKeyIsDRM to 1 return new DRMExtractor(source, originalMime); } else if (!strncmp(mime, "drm+container_based+", 20)) { mime = originalMime; + isDrm = true; } else { return NULL; } } + MediaExtractor *ret = NULL; if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG4) || !strcasecmp(mime, "audio/mp4")) { - return new MPEG4Extractor(source); + ret = new MPEG4Extractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) { - return new MP3Extractor(source, meta); + ret = new MP3Extractor(source, meta); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB) || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) { - return new AMRExtractor(source); + ret = new AMRExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)) { - return new FLACExtractor(source); + ret = new FLACExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WAV)) { - return new WAVExtractor(source); + ret = new WAVExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_OGG)) { - return new OggExtractor(source); + ret = new OggExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MATROSKA)) { - return new MatroskaExtractor(source); + ret = new MatroskaExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_MPEG2TS)) { - return new MPEG2TSExtractor(source); + ret = new MPEG2TSExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_CONTAINER_WVM)) { - return new WVMExtractor(source); + ret = new WVMExtractor(source); } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC_ADTS)) { - return new AACExtractor(source); + ret = new AACExtractor(source); + } + if (ret != NULL && isDrm) { + ret->getMetaData()->setInt32(kKeyIsDRM, 1); } - return NULL; + return ret; } } // namespace android diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index 600de7c3e03d..ea3b80114984 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -272,6 +272,12 @@ VideoFrame *StagefrightMetadataRetriever::getFrameAtTime( return NULL; } + int32_t drm = 0; + if (mExtractor->getMetaData()->findInt32(kKeyIsDRM, &drm) && drm != 0) { + LOGE("frame grab not allowed."); + return NULL; + } + size_t n = mExtractor->countTracks(); size_t i; for (i = 0; i < n; ++i) { diff --git a/media/libstagefright/colorconversion/ColorConverter.cpp b/media/libstagefright/colorconversion/ColorConverter.cpp index d518c9768384..3b92e5d0072e 100644 --- a/media/libstagefright/colorconversion/ColorConverter.cpp +++ b/media/libstagefright/colorconversion/ColorConverter.cpp @@ -187,7 +187,7 @@ status_t ColorConverter::convertCbYCrY( status_t ColorConverter::convertYUV420Planar( const BitmapParams &src, const BitmapParams &dst) { - if (!((dst.mWidth & 3) == 0 + if (!((dst.mWidth & 1) == 0 && (src.mCropLeft & 1) == 0 && src.cropWidth() == dst.cropWidth() && src.cropHeight() == dst.cropHeight())) { diff --git a/media/tests/CameraBrowser/AndroidManifest.xml b/media/tests/CameraBrowser/AndroidManifest.xml index f167f4bec542..fccb3ca32abb 100644 --- a/media/tests/CameraBrowser/AndroidManifest.xml +++ b/media/tests/CameraBrowser/AndroidManifest.xml @@ -2,7 +2,6 @@ package="com.android.camerabrowser"> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> - <uses-permission android:name="android.permission.ACCESS_USB" /> <application android:label="@string/app_label" android:name="com.android.camerabrowser.CameraBrowserApplication"> @@ -12,20 +11,15 @@ <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> + <intent-filter> + <action android:name="android.hardware.action.USB_DEVICE_ATTACHED" /> + </intent-filter> + <meta-data android:name="android.hardware.action.USB_DEVICE_ATTACHED" + android:resource="@xml/device_filter" /> </activity> <activity android:name="StorageBrowser" /> <activity android:name="ObjectBrowser" /> <activity android:name="ObjectViewer" /> - -<!-- - <receiver android:name="UsbReceiver"> - <intent-filter> - <action android:name="android.hardware.action.USB_DEVICE_ATTACHED" /> - </intent-filter> - </receiver> ---> </application> - - </manifest> diff --git a/media/tests/CameraBrowser/res/xml/device_filter.xml b/media/tests/CameraBrowser/res/xml/device_filter.xml new file mode 100644 index 000000000000..36cd13da7f57 --- /dev/null +++ b/media/tests/CameraBrowser/res/xml/device_filter.xml @@ -0,0 +1,19 @@ +<?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> + <!-- filter for PTP devices --> + <usb-device class="6" subclass="1" protocol="1" /> +</resources> diff --git a/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java b/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java deleted file mode 100644 index 22d9443af6ee..000000000000 --- a/media/tests/CameraBrowser/src/com/android/camerabrowser/UsbReceiver.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.camerabrowser; - -import android.content.Context; -import android.content.Intent; -import android.content.BroadcastReceiver; -import android.hardware.UsbDevice; -import android.hardware.UsbManager; -import android.mtp.MtpClient; -import android.os.Bundle; -import android.os.Parcelable; -import android.util.Log; - -public class UsbReceiver extends BroadcastReceiver -{ - private static final String TAG = "UsbReceiver"; - - @Override - public void onReceive(Context context, Intent intent) { - Log.d(TAG, "onReceive " + intent); - if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(intent.getAction())) { - UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - if (MtpClient.isCamera(device)) { - String deviceName = device.getDeviceName(); - Log.d(TAG, "Got camera: " + deviceName); - intent = new Intent(context, StorageBrowser.class); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra("device", deviceName); - context.startActivity(intent); - } - } - } -} diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java index 988b229474b6..a6cf3551ed40 100755 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java @@ -21,9 +21,10 @@ import com.android.mediaframeworktest.performance.MediaPlayerPerformance; import com.android.mediaframeworktest.performance.VideoEditorPerformance; import junit.framework.TestSuite; +import android.os.Bundle; import android.test.InstrumentationTestRunner; import android.test.InstrumentationTestSuite; - +import android.util.Log; /** * Instrumentation Test Runner for all MediaPlayer tests. @@ -36,19 +37,30 @@ import android.test.InstrumentationTestSuite; public class MediaFrameworkPerfTestRunner extends InstrumentationTestRunner { + public static boolean mGetNativeHeapDump = false; + + + @Override + public TestSuite getAllTests() { + TestSuite suite = new InstrumentationTestSuite(this); + suite.addTestSuite(MediaPlayerPerformance.class); + /* Video Editor performance Test cases */ + suite.addTestSuite(VideoEditorPerformance.class); + return suite; + } - @Override - public TestSuite getAllTests() { - TestSuite suite = new InstrumentationTestSuite(this); - suite.addTestSuite(MediaPlayerPerformance.class); - /*Video Editor performance Test cases*/ - suite.addTestSuite(VideoEditorPerformance.class); - return suite; - } + @Override + public ClassLoader getLoader() { + return MediaFrameworkTestRunner.class.getClassLoader(); + } - @Override - public ClassLoader getLoader() { - return MediaFrameworkTestRunner.class.getClassLoader(); - } + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + String get_heap_dump = (String) icicle.get("get_heap_dump"); + if (get_heap_dump != null) { + mGetNativeHeapDump = true; + } + } } diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaTestUtil.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaTestUtil.java new file mode 100755 index 000000000000..0183b5df8d59 --- /dev/null +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaTestUtil.java @@ -0,0 +1,45 @@ +/* + * 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.android.mediaframeworktest; + +import java.io.FileOutputStream; + +import android.os.Debug; +import android.os.Environment; + +/** + * + * Utilities for media framework test. + * + */ +public class MediaTestUtil { + private MediaTestUtil(){ + } + + private static final String STORAGE_PATH = + Environment.getExternalStorageDirectory().toString(); + + //Catpure the heapdump for memory leaksage analysis\ + public static void getNativeHeapDump (String name) throws Exception { + System.gc(); + System.runFinalization(); + Thread.sleep(1000); + FileOutputStream o = new FileOutputStream(STORAGE_PATH + '/' +name + ".dump"); + Debug.dumpNativeHeap(o.getFD()); + o.close(); + } +}
\ No newline at end of file diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java index ce6db68aab43..82df6690c571 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaRecorderTest.java @@ -28,7 +28,7 @@ import android.media.MediaRecorder; import android.media.EncoderCapabilities; import android.media.EncoderCapabilities.VideoEncoderCap; import android.media.EncoderCapabilities.AudioEncoderCap; -import android.test.ActivityInstrumentationTestCase; +import android.test.ActivityInstrumentationTestCase2; import android.util.Log; import android.view.SurfaceHolder; import android.view.SurfaceView; @@ -42,7 +42,7 @@ import java.util.List; /** * Junit / Instrumentation test case for the media recorder api */ -public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFrameworkTest> { +public class MediaRecorderTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { private String TAG = "MediaRecorderTest"; private int mOutputDuration =0; private int mOutputVideoWidth = 0; @@ -62,9 +62,9 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram } protected void setUp() throws Exception { - super.setUp(); - Log.v(TAG,"create the media recorder"); + getActivity(); mRecorder = new MediaRecorder(); + super.setUp(); } private void recordVideo(int frameRate, int width, int height, @@ -199,8 +199,6 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram return false; } - - private void getOutputVideoProperty(String outputFilePath) { MediaPlayer mediaPlayer = new MediaPlayer(); try { @@ -215,8 +213,6 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram Thread.sleep(1000); mOutputVideoHeight = mediaPlayer.getVideoHeight(); mOutputVideoWidth = mediaPlayer.getVideoWidth(); - //mOutputVideoHeight = CodecTest.videoHeight(outputFilePath); - //mOutputVideoWidth = CodecTest.videoWidth(outputFilePath); mediaPlayer.release(); } catch (Exception e) { Log.v(TAG, e.toString()); @@ -224,11 +220,6 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram } } - private void removeFile(String filePath) { - File fileRemove = new File(filePath); - fileRemove.delete(); - } - private boolean validateVideo(String filePath, int width, int height) { boolean validVideo = false; getOutputVideoProperty(filePath); @@ -237,72 +228,9 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram validVideo = true; } Log.v(TAG, "width = " + mOutputVideoWidth + " height = " + mOutputVideoHeight + " Duration = " + mOutputDuration); - //removeFile(filePath); return validVideo; } - - - //Format: HVGA h263 - @Suppress - public void testHVGAH263() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 480, 320, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_HVGA_H263, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_HVGA_H263, 480, 320); - assertTrue("HVGAH263", videoRecordedResult); - } - - //Format: QVGA h263 - @Suppress - public void testQVGAH263() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 320, 240, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_QVGA_H263, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_QVGA_H263, 320, 240); - assertTrue("QVGAH263", videoRecordedResult); - } - - //Format: SQVGA h263 - @Suppress - public void testSQVGAH263() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 240, 160, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_SQVGA_H263, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_SQVGA_H263, 240, 160); - assertTrue("SQVGAH263", videoRecordedResult); - } - - //Format: QCIF h263 - @LargeTest - public void testQCIFH263() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_QCIF_H263, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_QCIF_H263, 176, 144); - assertTrue("QCIFH263", videoRecordedResult); - } - - //Format: CIF h263 - @LargeTest - public void testCIFH263() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_CIF_H263, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_CIF_H263, 352, 288); - assertTrue("CIFH263", videoRecordedResult); - } - - - - @LargeTest - public void testVideoOnly() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_VIDEO_3GP, true); - videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 176, 144); - assertTrue("QCIFH263 Video Only", videoRecordedResult); - } - + @LargeTest /* * This test case set the camera in portrait mode. @@ -332,74 +260,6 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram assertTrue("PortraitH263", videoRecordedResult); } - @Suppress - public void testHVGAMP4() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 480, 320, MediaRecorder.VideoEncoder.MPEG_4_SP, - MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_HVGA_MP4, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_HVGA_MP4, 480, 320); - assertTrue("HVGAMP4", videoRecordedResult); - } - - @Suppress - public void testQVGAMP4() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 320, 240, MediaRecorder.VideoEncoder.MPEG_4_SP, - MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_QVGA_MP4, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_QVGA_MP4, 320, 240); - assertTrue("QVGAMP4", videoRecordedResult); - } - - @Suppress - public void testSQVGAMP4() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 240, 160, MediaRecorder.VideoEncoder.MPEG_4_SP, - MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_SQVGA_MP4, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_SQVGA_MP4, 240, 160); - assertTrue("SQVGAMP4", videoRecordedResult); - } - - //Format: QCIF MP4 - @LargeTest - public void testQCIFMP4() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.MPEG_4_SP, - MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_QCIF_MP4, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_QCIF_MP4, 176, 144); - assertTrue("QCIFMP4", videoRecordedResult); - } - - - //Format: CIF MP4 - @LargeTest - public void testCIFMP4() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP, - MediaRecorder.OutputFormat.MPEG_4, MediaNames.RECORDED_CIF_MP4, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_CIF_MP4, 352, 288); - assertTrue("CIFMP4", videoRecordedResult); - } - - - //Format: CIF MP4 output format 3gpp - @LargeTest - public void testCIFMP43GPP() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 352, 288, MediaRecorder.VideoEncoder.MPEG_4_SP, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 352, 288); - assertTrue("CIFMP4 3GPP", videoRecordedResult); - } - - @LargeTest - public void testQCIFH2633GPP() throws Exception { - boolean videoRecordedResult = false; - recordVideo(15, 176, 144, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false); - videoRecordedResult = validateVideo(MediaNames.RECORDED_VIDEO_3GP, 176, 144); - assertTrue("QCIFH263 3GPP", videoRecordedResult); - } - @LargeTest public void testInvalidVideoPath() throws Exception { boolean isTestInvalidVideoPathSuccessful = false; @@ -408,23 +268,6 @@ public class MediaRecorderTest extends ActivityInstrumentationTestCase<MediaFram assertTrue("Invalid outputFile Path", isTestInvalidVideoPathSuccessful); } - @Suppress - public void testInvalidVideoSize() throws Exception { - boolean isTestInvalidVideoSizeSuccessful = false; - isTestInvalidVideoSizeSuccessful = invalidRecordSetting(15, 800, 600, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false); - assertTrue("Invalid video Size", isTestInvalidVideoSizeSuccessful); - } - - @Suppress - @LargeTest - public void testInvalidFrameRate() throws Exception { - boolean isTestInvalidFrameRateSuccessful = false; - isTestInvalidFrameRateSuccessful = invalidRecordSetting(50, 176, 144, MediaRecorder.VideoEncoder.H263, - MediaRecorder.OutputFormat.THREE_GPP, MediaNames.RECORDED_VIDEO_3GP, false); - assertTrue("Invalid FrameRate", isTestInvalidFrameRateSuccessful); - } - @LargeTest //test cases for the new codec public void testDeviceSpecificCodec() throws Exception { diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java index 0e3029bbb3d7..34affa7b1cb7 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/MediaPlayerPerformance.java @@ -17,7 +17,9 @@ package com.android.mediaframeworktest.performance; import com.android.mediaframeworktest.MediaFrameworkTest; +import com.android.mediaframeworktest.MediaFrameworkPerfTestRunner; import com.android.mediaframeworktest.MediaNames; +import com.android.mediaframeworktest.MediaTestUtil; import android.database.sqlite.SQLiteDatabase; import android.hardware.Camera; @@ -27,7 +29,7 @@ import android.media.MediaRecorder; import android.os.ConditionVariable; import android.os.Looper; import android.os.SystemClock; -import android.test.ActivityInstrumentationTestCase; +import android.test.ActivityInstrumentationTestCase2; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.Suppress; import android.util.Log; @@ -52,7 +54,7 @@ import android.hardware.Camera.PreviewCallback; * Junit / Instrumentation - performance measurement for media player and * recorder */ -public class MediaPlayerPerformance extends ActivityInstrumentationTestCase<MediaFrameworkTest> { +public class MediaPlayerPerformance extends ActivityInstrumentationTestCase2<MediaFrameworkTest> { private String TAG = "MediaPlayerPerformance"; @@ -87,6 +89,15 @@ public class MediaPlayerPerformance extends ActivityInstrumentationTestCase<Medi protected void setUp() throws Exception { super.setUp(); + getActivity(); + if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump) + MediaTestUtil.getNativeHeapDump(this.getName() + "_before"); + } + + protected void tearDown() throws Exception { + super.tearDown(); + if (MediaFrameworkPerfTestRunner.mGetNativeHeapDump) + MediaTestUtil.getNativeHeapDump(this.getName() + "_after"); } public void createDB() { diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png Binary files differindex e4d5a328bdb3..7b54daff94c7 100644 --- a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png +++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_back_ime_default.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png Binary files differindex 9f72549353c6..87a67c9cf474 100644 --- a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg.png diff --git a/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png Binary files differnew file mode 100644 index 000000000000..7f86fb35f5e0 --- /dev/null +++ b/packages/SystemUI/res/drawable-xlarge-mdpi/recents_thumbnail_bg_press.png diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml index d7e16337d47f..bfa6c36a096e 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_item.xml @@ -22,14 +22,14 @@ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="wrap_content" - android:layout_width="156dip"> + android:layout_width="@dimen/status_bar_recents_thumbnail_view_width"> <ImageView android:id="@+id/app_thumbnail" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" - android:layout_marginLeft="105dip" + android:layout_marginLeft="@dimen/status_bar_recents_thumbnail_left_margin" android:scaleType="center" /> @@ -40,8 +40,8 @@ android:layout_alignParentTop="true" android:layout_marginLeft="123dip" android:layout_marginTop="16dip" - android:maxWidth="64dip" - android:maxHeight="64dip" + android:maxWidth="@dimen/status_bar_recents_thumbnail_max_width" + android:maxHeight="@dimen/status_bar_recents_thumbnail_max_height" android:adjustViewBounds="true" /> diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml index ecd2b6f225c7..4be57a20c2ca 100644 --- a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel.xml @@ -36,36 +36,35 @@ <LinearLayout android:id="@+id/recents_glow" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="horizontal" - android:layout_marginBottom="-28dip" + android:layout_marginBottom="-52dip" android:layout_gravity="bottom" - android:background="@drawable/recents_blue_glow"> + android:background="@drawable/recents_blue_glow" + android:orientation="horizontal" + > - <LinearLayout android:id="@+id/recents_container" - android:layout_width="356dip" + <ListView android:id="@+id/recents_container" + android:layout_width="@dimen/status_bar_recents_width" android:layout_height="wrap_content" - android:orientation="vertical" android:layout_marginRight="100dip" + android:divider="@null" + android:scrollingCache="true" + android:stackFromBottom="true" + android:fadingEdge="vertical" + android:scrollbars="none" + android:fadingEdgeLength="30dip" + android:listSelector="@drawable/recents_thumbnail_bg_press" /> </LinearLayout> </FrameLayout> - <!-- The outer FrameLayout is just used as an opaque background for the dismiss icon --> - <FrameLayout + <View android:id="@+id/recents_dismiss_button" android:layout_width="80px" android:layout_height="@*android:dimen/status_bar_height" android:layout_alignParentBottom="true" android:layout_alignParentLeft="true" - android:background="#ff000000"> - - <View android:id="@+id/recents_dismiss_button" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:background="@drawable/ic_sysbar_back_ime" - /> - - </FrameLayout> + android:background="@drawable/ic_sysbar_back_ime" + /> </com.android.systemui.statusbar.tablet.RecentAppsPanel> diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel_footer.xml b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel_footer.xml new file mode 100644 index 000000000000..4d14d1fb9fe2 --- /dev/null +++ b/packages/SystemUI/res/layout-xlarge/status_bar_recent_panel_footer.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* apps/common/assets/default/default/skins/StatusBar.xml +** +** Copyright 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. +*/ +--> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/listview_footer_padding" + android:layout_height="24dip" + android:layout_width="match_parent"> +</FrameLayout> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 93cf3778bc9c..88cd43c74da0 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -2,21 +2,34 @@ <!-- * Copyright (c) 2006, 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 + * 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 + * 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 + * 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> <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. --> <dimen name="status_bar_edge_ignore">5dp</dimen> + + <!-- Recent Applications parameters --> + <!-- Width of a recent app view, including all content --> + <dimen name="status_bar_recents_thumbnail_view_width">156dp</dimen> + <!-- How far the thumbnail for a recent app appears from left edge --> + <dimen name="status_bar_recents_thumbnail_left_margin">110dp</dimen> + <!-- Upper width limit for application icon --> + <dimen name="status_bar_recents_thumbnail_max_width">64dp</dimen> + <!-- Upper height limit for application icon --> + <dimen name="status_bar_recents_thumbnail_max_height">64dp</dimen> + <!-- Width of scrollable area in recents --> + <dimen name="status_bar_recents_width">356dp</dimen> + </resources> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java index e0d558f2580d..ebe1a7c9c622 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/RecentAppsPanel.java @@ -40,37 +40,43 @@ import android.graphics.RectF; import android.graphics.Shader.TileMode; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; +import android.os.Parcelable; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.util.Slog; +import android.view.LayoutInflater; import android.view.View; -import android.view.View.OnClickListener; -import android.view.animation.DecelerateInterpolator; +import android.view.ViewGroup; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemClickListener; +import android.widget.BaseAdapter; import android.widget.ImageView; -import android.widget.LinearLayout; +import android.widget.ListView; import android.widget.RelativeLayout; import android.widget.TextView; import com.android.systemui.R; -public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, OnClickListener { +public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, OnItemClickListener { private static final int GLOW_PADDING = 15; private static final String TAG = "RecentAppsPanel"; private static final boolean DEBUG = TabletStatusBar.DEBUG; - private static final int DISPLAY_TASKS_PORTRAIT = 7; // Limited by max binder transaction size - private static final int DISPLAY_TASKS_LANDSCAPE = 5; // number of recent tasks to display - private static final int MAX_TASKS = DISPLAY_TASKS_PORTRAIT + 1; // allow extra for non-apps + private static final int DISPLAY_TASKS = 20; + private static final int MAX_TASKS = DISPLAY_TASKS + 1; // allow extra for non-apps + private static final int BOTTOM_OFFSET = 28; // TODO: Get from dimens.xml private TabletStatusBar mBar; private ArrayList<ActivityDescription> mActivityDescriptions; private int mIconDpi; private View mRecentsScrim; private View mRecentsGlowView; - private LinearLayout mRecentsContainer; + private ListView mRecentsContainer; private Bitmap mGlowBitmap; private boolean mShowing; private Choreographer mChoreo; private View mRecentsDismissButton; + private ActvityDescriptionAdapter mListAdapter; + protected int mLastVisibleItem; static class ActivityDescription { int id; @@ -98,6 +104,63 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O } }; + private static class ViewHolder { + private ImageView thumbnailView; + private ImageView iconView; + private TextView labelView; + private TextView descriptionView; + private ActivityDescription activityDescription; + } + + private class ActvityDescriptionAdapter extends BaseAdapter { + private LayoutInflater mInflater; + + public ActvityDescriptionAdapter(Context context) { + mInflater = LayoutInflater.from(context); + } + + public int getCount() { + return mActivityDescriptions != null ? mActivityDescriptions.size() : 0; + } + + public Object getItem(int position) { + return position; // we only need the index + } + + public long getItemId(int position) { + return position; // we just need something unique for this position + } + + public View getView(int position, View convertView, ViewGroup parent) { + ViewHolder holder; + if (convertView == null) { + convertView = mInflater.inflate(R.layout.status_bar_recent_item, null); + holder = new ViewHolder(); + holder.thumbnailView = (ImageView) convertView.findViewById(R.id.app_thumbnail); + holder.iconView = (ImageView) convertView.findViewById(R.id.app_icon); + holder.labelView = (TextView) convertView.findViewById(R.id.app_label); + holder.descriptionView = (TextView) convertView.findViewById(R.id.app_description); + convertView.setTag(holder); + } else { + holder = (ViewHolder) convertView.getTag(); + } + + // activityId is reverse since most recent appears at the bottom... + final int activityId = mActivityDescriptions.size() - position - 1; + + final ActivityDescription activityDescription = mActivityDescriptions.get(activityId); + final Bitmap thumb = activityDescription.thumbnail; + holder.thumbnailView.setImageBitmap(compositeBitmap(mGlowBitmap, thumb)); + holder.iconView.setImageDrawable(activityDescription.icon); + holder.labelView.setText(activityDescription.label); + holder.descriptionView.setText(activityDescription.description); + holder.thumbnailView.setTag(activityDescription); + holder.activityDescription = activityDescription; + + return convertView; + } + } + public boolean isInContentArea(int x, int y) { // use mRecentsContainer's exact bounds to determine horizontal position final int l = mRecentsContainer.getLeft(); @@ -267,9 +330,41 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O } @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + // Keep track of the last visible item in the list so we can restore it + // to the bottom when the orientation changes. + int childCount = mRecentsContainer.getChildCount(); + if (childCount > 0) { + mLastVisibleItem = mRecentsContainer.getFirstVisiblePosition() + childCount - 1; + View view = mRecentsContainer.getChildAt(childCount - 1); + final int distanceFromBottom = mRecentsContainer.getHeight() - view.getTop(); + //final int distanceFromBottom = view.getHeight() + BOTTOM_OFFSET; + + // This has to happen post-layout, so run it "in the future" + post(new Runnable() { + public void run() { + mRecentsContainer.setSelectionFromTop(mLastVisibleItem, + mRecentsContainer.getHeight() - distanceFromBottom); + } + }); + } + } + + @Override protected void onFinishInflate() { super.onFinishInflate(); - mRecentsContainer = (LinearLayout) findViewById(R.id.recents_container); + LayoutInflater inflater = (LayoutInflater) + mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + + mRecentsContainer = (ListView) findViewById(R.id.recents_container); + View footer = inflater.inflate(R.layout.status_bar_recent_panel_footer, + mRecentsContainer, false); + mRecentsContainer.setScrollbarFadingEnabled(true); + mRecentsContainer.addFooterView(footer); + mRecentsContainer.setAdapter(mListAdapter = new ActvityDescriptionAdapter(mContext)); + mRecentsContainer.setOnItemClickListener(this); + mRecentsGlowView = findViewById(R.id.recents_glow); mRecentsScrim = (View) findViewById(R.id.recents_bg_protect); mChoreo = new Choreographer(this, mRecentsScrim, mRecentsGlowView); @@ -287,20 +382,16 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O } @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - // we show more in portrait mode, so update UI if orientation changes - updateUiElements(newConfig, false); - } - - @Override protected void onVisibilityChanged(View changedView, int visibility) { super.onVisibilityChanged(changedView, visibility); if (DEBUG) Log.v(TAG, "onVisibilityChanged(" + changedView + ", " + visibility + ")"); if (visibility == View.VISIBLE && changedView == this) { refreshApplicationList(); - mRecentsContainer.setScrollbarFadingEnabled(true); - mRecentsContainer.scrollTo(0, 0); + post(new Runnable() { + public void run() { + mRecentsContainer.setSelection(mActivityDescriptions.size() - 1); + } + }); } } @@ -402,11 +493,12 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O private void refreshApplicationList() { mActivityDescriptions = getRecentTasks(); + mListAdapter.notifyDataSetInvalidated(); if (mActivityDescriptions.size() > 0) { - updateUiElements(getResources().getConfiguration(), true); + mLastVisibleItem = mActivityDescriptions.size() - 1; // scroll to bottom after reloading + updateUiElements(getResources().getConfiguration()); } else { // Immediately hide this panel - mShowing = false; hide(false); } } @@ -426,44 +518,29 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O canvas.drawBitmap(thumbnail, new Rect(0, 0, srcWidth-1, srcHeight-1), new RectF(GLOW_PADDING, - GLOW_PADDING - 4.0f, - outBitmap.getWidth() - GLOW_PADDING + 2.0f, - outBitmap.getHeight() - GLOW_PADDING + 3.0f), paint); + GLOW_PADDING - 7.0f, + outBitmap.getWidth() - GLOW_PADDING + 3.0f, + outBitmap.getHeight() - GLOW_PADDING + 7.0f), paint); } return outBitmap; } - private void updateUiElements(Configuration config, boolean animate) { - mRecentsContainer.removeAllViews(); - - final int first = 0; - final boolean isPortrait = config.orientation == Configuration.ORIENTATION_PORTRAIT; - final int taskCount = isPortrait ? DISPLAY_TASKS_PORTRAIT : DISPLAY_TASKS_LANDSCAPE; - final int last = Math.min(mActivityDescriptions.size(), taskCount) - 1; - for (int i = last; i >= first; i--) { - ActivityDescription activityDescription = mActivityDescriptions.get(i); - View view = View.inflate(mContext, R.layout.status_bar_recent_item, null); - ImageView appThumbnail = (ImageView) view.findViewById(R.id.app_thumbnail); - ImageView appIcon = (ImageView) view.findViewById(R.id.app_icon); - TextView appLabel = (TextView) view.findViewById(R.id.app_label); - TextView appDesc = (TextView) view.findViewById(R.id.app_description); - final Bitmap thumb = activityDescription.thumbnail; - appThumbnail.setImageBitmap(compositeBitmap(mGlowBitmap, thumb)); - appIcon.setImageDrawable(activityDescription.icon); - appLabel.setText(activityDescription.label); - appDesc.setText(activityDescription.description); - appThumbnail.setOnClickListener(this); - appThumbnail.setTag(activityDescription); - mRecentsContainer.addView(view); - } + private void updateUiElements(Configuration config) { + final int items = mActivityDescriptions.size(); + + mRecentsContainer.setVisibility(items > 0 ? View.VISIBLE : View.GONE); + mRecentsGlowView.setVisibility(items > 0 ? View.VISIBLE : View.GONE); + } - int views = mRecentsContainer.getChildCount(); - mRecentsContainer.setVisibility(views > 0 ? View.VISIBLE : View.GONE); - mRecentsGlowView.setVisibility(views > 0 ? View.VISIBLE : View.GONE); + private void hide(boolean animate) { + if (!animate) { + setVisibility(View.GONE); + } + mBar.animateCollapse(); } - public void onClick(View v) { - ActivityDescription ad = (ActivityDescription)v.getTag(); + public void onItemClick(AdapterView<?> parent, View view, int position, long id) { + ActivityDescription ad = ((ViewHolder) view.getTag()).activityDescription; final ActivityManager am = (ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE); if (ad.id >= 0) { @@ -478,11 +555,4 @@ public class RecentAppsPanel extends RelativeLayout implements StatusBarPanel, O } hide(true); } - - private void hide(boolean animate) { - setVisibility(View.GONE); - if (animate) { - mBar.animateCollapse(); - } - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java index 233d601b6fda..f0408a28a00f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java @@ -267,6 +267,8 @@ public class TabletStatusBar extends StatusBar implements lp.gravity = Gravity.BOTTOM | Gravity.LEFT; lp.setTitle("RecentsPanel"); lp.windowAnimations = R.style.Animation_RecentPanel; + lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED + | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING; WindowManagerImpl.getDefault().addView(mRecentsPanel, lp); mRecentsPanel.setBar(this); @@ -509,7 +511,7 @@ public class TabletStatusBar extends StatusBar implements final int peekIndex = m.arg1; if (peekIndex < N) { //Slog.d(TAG, "loading peek: " + peekIndex); - NotificationData.Entry entry = + NotificationData.Entry entry = mNotificationDNDMode ? mNotificationDNDDummyEntry : mNotificationData.get(N-1-peekIndex); @@ -555,7 +557,7 @@ public class TabletStatusBar extends StatusBar implements final int N = mNotificationData.size(); if (mNotificationPeekIndex >= 0 && mNotificationPeekIndex < N) { - NotificationData.Entry entry = + NotificationData.Entry entry = mNotificationDNDMode ? mNotificationDNDDummyEntry : mNotificationData.get(N-1-mNotificationPeekIndex); @@ -584,6 +586,8 @@ public class TabletStatusBar extends StatusBar implements case MSG_OPEN_RECENTS_PANEL: if (DEBUG) Slog.d(TAG, "opening recents panel"); if (mRecentsPanel != null) { + disable(StatusBarManager.DISABLE_NAVIGATION + | StatusBarManager.DISABLE_BACK); mRecentsPanel.setVisibility(View.VISIBLE); mRecentsPanel.show(true, true); } @@ -591,6 +595,7 @@ public class TabletStatusBar extends StatusBar implements case MSG_CLOSE_RECENTS_PANEL: if (DEBUG) Slog.d(TAG, "closing recents panel"); if (mRecentsPanel != null && mRecentsPanel.isShowing()) { + disable(StatusBarManager.DISABLE_NONE); mRecentsPanel.show(false, true); } break; @@ -701,7 +706,7 @@ public class TabletStatusBar extends StatusBar implements && oldContentView.getLayoutId() == contentView.getLayoutId(); ViewGroup rowParent = (ViewGroup) oldEntry.row.getParent(); boolean orderUnchanged = notification.notification.when==oldNotification.notification.when - && notification.priority == oldNotification.priority; + && notification.priority == oldNotification.priority; // priority now encompasses isOngoing() boolean isLastAnyway = rowParent.indexOfChild(oldEntry.row) == rowParent.getChildCount()-1; if (contentsUnchanged && (orderUnchanged || isLastAnyway)) { diff --git a/packages/WAPPushManager/Android.mk b/packages/WAPPushManager/Android.mk new file mode 100644 index 000000000000..c1d8f4b6cdc9 --- /dev/null +++ b/packages/WAPPushManager/Android.mk @@ -0,0 +1,20 @@ +# Copyright 2007-2008 The Android Open Source Project + + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := WAPPushManager + +LOCAL_STATIC_JAVA_LIBRARIES += android-common + +LOCAL_PROGUARD_FLAGS := -include $(LOCAL_PATH)/proguard.flags + +include $(BUILD_PACKAGE) + +# This finds and builds the test apk as well, so a single make does both. +include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/WAPPushManager/AndroidManifest.xml b/packages/WAPPushManager/AndroidManifest.xml new file mode 100644 index 000000000000..89e9d6ab8685 --- /dev/null +++ b/packages/WAPPushManager/AndroidManifest.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* + * Copyright (C) 2007-2008 The Android Open Source Project + * + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.smspush"> + + <permission android:name="com.android.smspush.WAPPUSH_MANAGER_BIND" + android:protectionLevel="signatureOrSystem" /> + + <original-package android:name="com.android.smspush" /> + <application> + <service android:name=".WapPushManager" + android:permission="com.android.smspush.WAPPUSH_MANAGER_BIND" + android:exported="true"> + <intent-filter> + <action android:name="com.android.internal.telephony.IWapPushManager"></action> + </intent-filter> + </service> + </application> + + +</manifest> diff --git a/packages/WAPPushManager/CleanSpec.mk b/packages/WAPPushManager/CleanSpec.mk new file mode 100644 index 000000000000..b84e1b65e75e --- /dev/null +++ b/packages/WAPPushManager/CleanSpec.mk @@ -0,0 +1,49 @@ +# 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. +# + +# If you don't need to do a full clean build but would like to touch +# a file or delete some intermediate files, add a clean step to the end +# of the list. These steps will only be run once, if they haven't been +# run before. +# +# E.g.: +# $(call add-clean-step, touch -c external/sqlite/sqlite3.h) +# $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates) +# +# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with +# files that are missing or have been moved. +# +# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory. +# Use $(OUT_DIR) to refer to the "out" directory. +# +# If you need to re-do something that's already mentioned, just copy +# the command and add it to the bottom of the list. E.g., if a change +# that you made last week required touching a file and a change you +# made today requires touching the same file, just copy the old +# touch step and add it to the end of the list. +# +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ + +# For example: +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates) +#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates) +#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f) +#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*) + +# ************************************************ +# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST +# ************************************************ diff --git a/packages/WAPPushManager/MODULE_LICENSE_APACHE2 b/packages/WAPPushManager/MODULE_LICENSE_APACHE2 new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/packages/WAPPushManager/MODULE_LICENSE_APACHE2 diff --git a/packages/WAPPushManager/NOTICE b/packages/WAPPushManager/NOTICE new file mode 100644 index 000000000000..c5b1efa7aac7 --- /dev/null +++ b/packages/WAPPushManager/NOTICE @@ -0,0 +1,190 @@ + + Copyright (c) 2005-2008, The Android Open Source Project + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + + 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. + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + diff --git a/packages/WAPPushManager/proguard.flags b/packages/WAPPushManager/proguard.flags new file mode 100644 index 000000000000..d09887b2c47e --- /dev/null +++ b/packages/WAPPushManager/proguard.flags @@ -0,0 +1,18 @@ + +#apply method is dynamically referenced by the reflection class. +-keep class android.app.ContextImpl$SharedPreferencesImpl$EditorImpl { + void apply(); +} +-keep class android.content.SharedPreferences$Editor { + void apply(); +} + +#WapPushManager is referenced only by AndroidManifest.xml +-keep class com.android.smspush.WapPushManager { +#CTS module method + public boolean isDataExist(java.lang.String, java.lang.String, + java.lang.String, java.lang.String); + public boolean verifyData(java.lang.String, java.lang.String, + java.lang.String, java.lang.String, int, boolean, boolean); +} + diff --git a/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java new file mode 100644 index 000000000000..96e037797b98 --- /dev/null +++ b/packages/WAPPushManager/src/com/android/smspush/WapPushManager.java @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.smspush; + +import android.app.Service; +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.database.sqlite.SQLiteOpenHelper; +import android.database.sqlite.SQLiteDatabase; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.android.internal.telephony.IWapPushManager; +import com.android.internal.telephony.WapPushManagerParams; + +/** + * The WapPushManager service is implemented to process incoming + * WAP Push messages and to maintain the Receiver Application/Application + * ID mapping. The WapPushManager runs as a system service, and only the + * WapPushManager can update the WAP Push message and Receiver Application + * mapping (Application ID Table). When the device receives an SMS WAP Push + * message, the WapPushManager looks up the Receiver Application name in + * Application ID Table. If an application is found, the application is + * launched using its full component name instead of broadcasting an implicit + * Intent. If a Receiver Application is not found in the Application ID + * Table or the WapPushManager returns a process-further value, the + * telephony stack will process the message using existing message processing + * flow, and broadcast an implicit Intent. + */ +public class WapPushManager extends Service { + + private static final String LOG_TAG = "WAP PUSH"; + private static final String DATABASE_NAME = "wappush.db"; + private static final String APPID_TABLE_NAME = "appid_tbl"; + + /** + * Version number must be incremented when table structure is changed. + */ + private static final int WAP_PUSH_MANAGER_VERSION = 1; + private static final boolean DEBUG_SQL = false; + private static final boolean LOCAL_LOGV = false; + + /** + * Inner class that deals with application ID table + */ + private class WapPushManDBHelper extends SQLiteOpenHelper { + WapPushManDBHelper(Context context) { + super(context, DATABASE_NAME, null, WAP_PUSH_MANAGER_VERSION); + if (LOCAL_LOGV) Log.v(LOG_TAG, "helper instance created."); + } + + @Override + public void onCreate(SQLiteDatabase db) { + if (LOCAL_LOGV) Log.v(LOG_TAG, "db onCreate."); + String sql = "CREATE TABLE " + APPID_TABLE_NAME + " (" + + "id INTEGER PRIMARY KEY, " + + "x_wap_application TEXT, " + + "content_type TEXT, " + + "package_name TEXT, " + + "class_name TEXT, " + + "app_type INTEGER, " + + "need_signature INTEGER, " + + "further_processing INTEGER, " + + "install_order INTEGER " + + ")"; + + if (DEBUG_SQL) Log.v(LOG_TAG, "sql: " + sql); + db.execSQL(sql); + } + + @Override + public void onUpgrade(SQLiteDatabase db, + int oldVersion, int newVersion) { + // TODO: when table structure is changed, need to dump and restore data. + /* + db.execSQL( + "drop table if exists "+APPID_TABLE_NAME); + onCreate(db); + */ + Log.w(LOG_TAG, "onUpgrade is not implemented yet. do nothing."); + } + + protected class queryData { + public String packageName; + public String className; + int appType; + int needSignature; + int furtherProcessing; + int installOrder; + } + + /** + * Query the latest receiver application info with supplied application ID and + * content type. + * @param app_id application ID to look up + * @param content_type content type to look up + */ + protected queryData queryLastApp(SQLiteDatabase db, + String app_id, String content_type) { + String sql = "select install_order, package_name, class_name, " + + " app_type, need_signature, further_processing" + + " from " + APPID_TABLE_NAME + + " where x_wap_application=\'" + app_id + "\'" + + " and content_type=\'" + content_type + "\'" + + " order by install_order desc"; + if (DEBUG_SQL) Log.v(LOG_TAG, "sql: " + sql); + Cursor cur = db.rawQuery(sql, null); + queryData ret = null; + + if (cur.moveToNext()) { + ret = new queryData(); + ret.installOrder = cur.getInt(cur.getColumnIndex("install_order")); + ret.packageName = cur.getString(cur.getColumnIndex("package_name")); + ret.className = cur.getString(cur.getColumnIndex("class_name")); + ret.appType = cur.getInt(cur.getColumnIndex("app_type")); + ret.needSignature = cur.getInt(cur.getColumnIndex("need_signature")); + ret.furtherProcessing = cur.getInt(cur.getColumnIndex("further_processing")); + } + cur.close(); + return ret; + } + + } + + /** + * The exported API implementations class + */ + private class IWapPushManagerStub extends IWapPushManager.Stub { + public Context mContext; + + public IWapPushManagerStub() { + + } + + /** + * Compare the package signature with WapPushManager package + */ + protected boolean signatureCheck(String package_name) { + PackageManager pm = mContext.getPackageManager(); + int match = pm.checkSignatures(mContext.getPackageName(), package_name); + + if (LOCAL_LOGV) Log.v(LOG_TAG, "compare signature " + mContext.getPackageName() + + " and " + package_name + ", match=" + match); + + return match == PackageManager.SIGNATURE_MATCH; + } + + /** + * Returns the status value of the message processing. + * The message will be processed as follows: + * 1.Look up Application ID Table with x-wap-application-id + content type + * 2.Check the signature of package name that is found in the + * Application ID Table by using PackageManager.checkSignature + * 3.Trigger the Application + * 4.Returns the process status value. + */ + public int processMessage(String app_id, String content_type, Intent intent) + throws RemoteException { + Log.d(LOG_TAG, "wpman processMsg " + app_id + ":" + content_type); + + WapPushManDBHelper dbh = getDatabase(mContext); + SQLiteDatabase db = dbh.getReadableDatabase(); + WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, app_id, content_type); + db.close(); + + if (lastapp == null) { + Log.w(LOG_TAG, "no receiver app found for " + app_id + ":" + content_type); + return WapPushManagerParams.APP_QUERY_FAILED; + } + if (LOCAL_LOGV) Log.v(LOG_TAG, "starting " + lastapp.packageName + + "/" + lastapp.className); + + if (lastapp.needSignature != 0) { + if (!signatureCheck(lastapp.packageName)) { + return WapPushManagerParams.SIGNATURE_NO_MATCH; + } + } + + if (lastapp.appType == WapPushManagerParams.APP_TYPE_ACTIVITY) { + //Intent intent = new Intent(Intent.ACTION_MAIN); + intent.setClassName(lastapp.packageName, lastapp.className); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.w(LOG_TAG, "invalid name " + + lastapp.packageName + "/" + lastapp.className); + return WapPushManagerParams.INVALID_RECEIVER_NAME; + } + } else { + intent.setClassName(mContext, lastapp.className); + intent.setComponent(new ComponentName(lastapp.packageName, + lastapp.className)); + if (mContext.startService(intent) == null) { + Log.w(LOG_TAG, "invalid name " + + lastapp.packageName + "/" + lastapp.className); + return WapPushManagerParams.INVALID_RECEIVER_NAME; + } + } + + return WapPushManagerParams.MESSAGE_HANDLED + | (lastapp.furtherProcessing == 1 ? + WapPushManagerParams.FURTHER_PROCESSING : 0); + } + + protected boolean appTypeCheck(int app_type) { + if (app_type == WapPushManagerParams.APP_TYPE_ACTIVITY || + app_type == WapPushManagerParams.APP_TYPE_SERVICE) { + return true; + } else { + return false; + } + } + + /** + * Returns true if adding the package succeeded. + */ + public boolean addPackage(String x_app_id, String content_type, + String package_name, String class_name, + int app_type, boolean need_signature, boolean further_processing) { + WapPushManDBHelper dbh = getDatabase(mContext); + SQLiteDatabase db = dbh.getWritableDatabase(); + WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type); + boolean ret = false; + boolean insert = false; + int sq = 0; + + if (!appTypeCheck(app_type)) { + Log.w(LOG_TAG, "invalid app_type " + app_type + ". app_type must be " + + WapPushManagerParams.APP_TYPE_ACTIVITY + " or " + + WapPushManagerParams.APP_TYPE_SERVICE); + return false; + } + + if (lastapp == null) { + insert = true; + sq = 0; + } else if (!lastapp.packageName.equals(package_name) || + !lastapp.className.equals(class_name)) { + insert = true; + sq = lastapp.installOrder + 1; + } + + if (insert) { + ContentValues values = new ContentValues(); + + values.put("x_wap_application", x_app_id); + values.put("content_type", content_type); + values.put("package_name", package_name); + values.put("class_name", class_name); + values.put("app_type", app_type); + values.put("need_signature", need_signature ? 1 : 0); + values.put("further_processing", further_processing ? 1 : 0); + values.put("install_order", sq); + db.insert(APPID_TABLE_NAME, null, values); + if (LOCAL_LOGV) Log.v(LOG_TAG, "add:" + x_app_id + ":" + content_type + + " " + package_name + "." + class_name + + ", newsq:" + sq); + ret = true; + } + + db.close(); + + return ret; + } + + /** + * Returns true if updating the package succeeded. + */ + public boolean updatePackage(String x_app_id, String content_type, + String package_name, String class_name, + int app_type, boolean need_signature, boolean further_processing) { + + if (!appTypeCheck(app_type)) { + Log.w(LOG_TAG, "invalid app_type " + app_type + ". app_type must be " + + WapPushManagerParams.APP_TYPE_ACTIVITY + " or " + + WapPushManagerParams.APP_TYPE_SERVICE); + return false; + } + + WapPushManDBHelper dbh = getDatabase(mContext); + SQLiteDatabase db = dbh.getWritableDatabase(); + WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type); + + if (lastapp == null) { + db.close(); + return false; + } + + ContentValues values = new ContentValues(); + String where = "x_wap_application=\'" + x_app_id + "\'" + + " and content_type=\'" + content_type + "\'" + + " and install_order=" + lastapp.installOrder; + + values.put("package_name", package_name); + values.put("class_name", class_name); + values.put("app_type", app_type); + values.put("need_signature", need_signature ? 1 : 0); + values.put("further_processing", further_processing ? 1 : 0); + + int num = db.update(APPID_TABLE_NAME, values, where, null); + if (LOCAL_LOGV) Log.v(LOG_TAG, "update:" + x_app_id + ":" + content_type + " " + + package_name + "." + class_name + + ", sq:" + lastapp.installOrder); + + db.close(); + + return num > 0; + } + + /** + * Returns true if deleting the package succeeded. + */ + public boolean deletePackage(String x_app_id, String content_type, + String package_name, String class_name) { + WapPushManDBHelper dbh = getDatabase(mContext); + SQLiteDatabase db = dbh.getWritableDatabase(); + String where = "x_wap_application=\'" + x_app_id + "\'" + + " and content_type=\'" + content_type + "\'" + + " and package_name=\'" + package_name + "\'" + + " and class_name=\'" + class_name + "\'"; + int num_removed = db.delete(APPID_TABLE_NAME, where, null); + + db.close(); + if (LOCAL_LOGV) Log.v(LOG_TAG, "deleted " + num_removed + " rows:" + + x_app_id + ":" + content_type + " " + + package_name + "." + class_name); + return num_removed > 0; + } + }; + + + /** + * Linux IPC Binder + */ + private final IWapPushManagerStub mBinder = new IWapPushManagerStub(); + + /** + * Default constructor + */ + public WapPushManager() { + super(); + mBinder.mContext = this; + } + + @Override + public IBinder onBind(Intent arg0) { + return mBinder; + } + + /** + * Application ID database instance + */ + private WapPushManDBHelper mDbHelper = null; + protected WapPushManDBHelper getDatabase(Context context) { + if (mDbHelper == null) { + if (LOCAL_LOGV) Log.v(LOG_TAG, "create new db inst."); + mDbHelper = new WapPushManDBHelper(context); + } + return mDbHelper; + } + + + /** + * This method is used for testing + */ + public boolean verifyData(String x_app_id, String content_type, + String package_name, String class_name, + int app_type, boolean need_signature, boolean further_processing) { + WapPushManDBHelper dbh = getDatabase(this); + SQLiteDatabase db = dbh.getReadableDatabase(); + WapPushManDBHelper.queryData lastapp = dbh.queryLastApp(db, x_app_id, content_type); + + db.close(); + + if (lastapp == null) return false; + + if (lastapp.packageName.equals(package_name) + && lastapp.className.equals(class_name) + && lastapp.appType == app_type + && lastapp.needSignature == (need_signature ? 1 : 0) + && lastapp.furtherProcessing == (further_processing ? 1 : 0)) { + return true; + } else { + return false; + } + } + + /** + * This method is used for testing + */ + public boolean isDataExist(String x_app_id, String content_type, + String package_name, String class_name) { + WapPushManDBHelper dbh = getDatabase(this); + SQLiteDatabase db = dbh.getReadableDatabase(); + boolean ret = dbh.queryLastApp(db, x_app_id, content_type) != null; + + db.close(); + return ret; + } + +} + diff --git a/packages/WAPPushManager/tests/Android.mk b/packages/WAPPushManager/tests/Android.mk new file mode 100644 index 000000000000..0a95b526cf1d --- /dev/null +++ b/packages/WAPPushManager/tests/Android.mk @@ -0,0 +1,38 @@ +# Copyright 2008, The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +# We only want this apk build for tests. +LOCAL_MODULE_TAGS := tests + +LOCAL_JAVA_LIBRARIES := android.test.runner + +# Include all test java files. +LOCAL_SRC_FILES := $(call all-java-files-under, src) +LOCAL_SRC_FILES += \ + src/com/android/smspush/unitTests/IDataVerify.aidl + + +# Notice that we don't have to include the src files of Email because, by +# running the tests using an instrumentation targeting Eamil, we +# automatically get all of its classes loaded into our environment. + +LOCAL_PACKAGE_NAME := WAPPushManagerTests + +LOCAL_INSTRUMENTATION_FOR := WAPPushManager + +include $(BUILD_PACKAGE) + diff --git a/packages/WAPPushManager/tests/AndroidManifest.xml b/packages/WAPPushManager/tests/AndroidManifest.xml new file mode 100644 index 000000000000..da7634fcfbb0 --- /dev/null +++ b/packages/WAPPushManager/tests/AndroidManifest.xml @@ -0,0 +1,71 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2008 The Android Open Source Project + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--> + +<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.smspush.unitTests"> + + + <uses-permission android:name="com.android.smspush.WAPPUSH_MANAGER_BIND" /> + <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" /> + <!--testing.../--> + <application android:icon="@drawable/icon" android:label="wappush test"> + <uses-library android:name="android.test.runner" /> + <activity android:name=".ClientTest" + android:label="wappush test"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <receiver android:name=".DrmReceiver" android:enabled="true"> + <intent-filter> + <action android:name="android.provider.Telephony.WAP_PUSH_RECEIVED" /> + <data android:mimeType="application/vnd.oma.drm.rights+xml" /> + <data android:value="application/vnd.oma.drm.rights+wbxml" /> + </intent-filter> + </receiver> + + <service android:enabled="true" android:name=".ReceiverService" + android:exported="true"/> + + <activity android:name=".ReceiverActivity" + android:exported="true" android:label="test receiver" /> + + <service android:name=".DataVerify" + android:exported="true"> + <intent-filter> + <action android:name="com.android.smspush.unitTests.IDataVerify" /> + </intent-filter> + </service> + + </application> + + <!-- + This declares that this application uses the instrumentation test runner targeting + the package of com.android.smspush. To run the tests use the command: + "adb shell am instrument -w + com.android.smspush.unitTests/android.test.InstrumentationTestRunner" + --> + <instrumentation android:name="android.test.InstrumentationTestRunner" + android:targetPackage="com.android.smspush" + android:label="Tests for WAPPushManager"/> + +</manifest> + diff --git a/packages/WAPPushManager/tests/res/drawable-hdpi/icon.png b/packages/WAPPushManager/tests/res/drawable-hdpi/icon.png Binary files differnew file mode 100644 index 000000000000..8074c4c571b8 --- /dev/null +++ b/packages/WAPPushManager/tests/res/drawable-hdpi/icon.png diff --git a/packages/WAPPushManager/tests/res/drawable-ldpi/icon.png b/packages/WAPPushManager/tests/res/drawable-ldpi/icon.png Binary files differnew file mode 100644 index 000000000000..1095584ec21f --- /dev/null +++ b/packages/WAPPushManager/tests/res/drawable-ldpi/icon.png diff --git a/packages/WAPPushManager/tests/res/drawable-mdpi/icon.png b/packages/WAPPushManager/tests/res/drawable-mdpi/icon.png Binary files differnew file mode 100644 index 000000000000..a07c69fa5a0f --- /dev/null +++ b/packages/WAPPushManager/tests/res/drawable-mdpi/icon.png diff --git a/packages/WAPPushManager/tests/res/layout/main.xml b/packages/WAPPushManager/tests/res/layout/main.xml new file mode 100644 index 000000000000..c7bdbb28d3df --- /dev/null +++ b/packages/WAPPushManager/tests/res/layout/main.xml @@ -0,0 +1,152 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright (C) 2010 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. +--> +<AbsoluteLayout +android:id="@+id/widget133" +android:layout_width="fill_parent" +android:layout_height="fill_parent" +xmlns:android="http://schemas.android.com/apk/res/android" +> +<EditText +android:id="@+id/app_id" +android:layout_width="wrap_content" +android:layout_height="wrap_content" +android:text="10" +android:textSize="18sp" +android:layout_x="0px" +android:layout_y="26px" +> +</EditText> +<EditText +android:id="@+id/cont" +android:layout_width="wrap_content" +android:layout_height="wrap_content" +android:text="20" +android:textSize="18sp" +android:layout_x="47px" +android:layout_y="26px" +> +</EditText> +<EditText +android:id="@+id/pkg" +android:layout_width="125px" +android:layout_height="wrap_content" +android:text="pkg" +android:textSize="18sp" +android:layout_x="0px" +android:layout_y="81px" +> +</EditText> +<EditText +android:id="@+id/cls" +android:layout_width="173px" +android:layout_height="wrap_content" +android:text="cls" +android:textSize="18sp" +android:layout_x="147px" +android:layout_y="81px" +> +</EditText> +<Button +android:id="@+id/addpkg" +android:layout_width="182px" +android:layout_height="wrap_content" +android:text="add/update package" +android:layout_x="15px" +android:layout_y="225px" +> +</Button> +<TextView +android:id="@+id/widget52" +android:layout_width="wrap_content" +android:layout_height="wrap_content" +android:text="input app_id, cont_type, pkg, cls" +android:textSize="18sp" +android:layout_x="0px" +android:layout_y="0px" +> +</TextView> +<Button +android:id="@+id/procmsg" +android:layout_width="109px" +android:layout_height="wrap_content" +android:text="process msg" +android:layout_x="197px" +android:layout_y="361px" +> +</Button> +<RadioGroup +android:id="@+id/widget137" +android:layout_width="83px" +android:layout_height="80px" +android:orientation="vertical" +android:layout_x="19px" +android:layout_y="137px" +> +<RadioButton +android:id="@+id/act" +android:layout_width="182px" +android:layout_height="wrap_content" +android:text="act" +android:checked="true" +> +</RadioButton> +<RadioButton +android:id="@+id/svc" +android:layout_width="wrap_content" +android:layout_height="wrap_content" +android:text="svc" +> +</RadioButton> +</RadioGroup> +<Button +android:id="@+id/delpkg" +android:layout_width="174px" +android:layout_height="wrap_content" +android:text="delete pkg" +android:layout_x="14px" +android:layout_y="283px" +> +</Button> +<EditText +android:id="@+id/pdu" +android:layout_width="186px" +android:layout_height="83px" +android:text="0006080302030aaf02905c030d6a0085070373616d706c6540646f636f6d6f2e6e652e6a700005c3072009102012345601" +android:textSize="18sp" +android:layout_x="10px" +android:layout_y="341px" +> +</EditText> +<CheckBox +android:id="@+id/ftr" +android:layout_width="wrap_content" +android:layout_height="wrap_content" +android:text="ftr_proc" +android:layout_x="143px" +android:layout_y="181px" +> +</CheckBox> +<CheckBox +android:id="@+id/sig" +android:layout_width="wrap_content" +android:layout_height="wrap_content" +android:text="nd_sig" +android:checked="true" +android:layout_x="142px" +android:layout_y="140px" +> +</CheckBox> +</AbsoluteLayout> diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java new file mode 100644 index 000000000000..78fd174313b7 --- /dev/null +++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ClientTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.smspush.unitTests; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.RadioButton; + +import com.android.internal.telephony.IWapPushManager; +import com.android.internal.telephony.WapPushManagerParams; +import com.android.internal.telephony.WapPushOverSms; +import com.android.internal.util.HexDump; +import com.android.smspush.WapPushManager; + +/** + * WapPushManager test application + */ +public class ClientTest extends Activity { + private static final String LOG_TAG = "WAP PUSH"; + + /** Called when the activity is first created. */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.main); + + Button addpbtn = (Button) findViewById(R.id.addpkg); + Button procbtn = (Button) findViewById(R.id.procmsg); + Button delbtn = (Button) findViewById(R.id.delpkg); + + Log.v(LOG_TAG, "activity created!!"); + + addpbtn.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + EditText app_id = (EditText) findViewById(R.id.app_id); + EditText cont = (EditText) findViewById(R.id.cont); + EditText pkg = (EditText) findViewById(R.id.pkg); + EditText cls = (EditText) findViewById(R.id.cls); + RadioButton act = (RadioButton) findViewById(R.id.act); + CheckBox sig = (CheckBox) findViewById(R.id.sig); + CheckBox ftr = (CheckBox) findViewById(R.id.ftr); + + try { + if (!mWapPushMan.addPackage( + app_id.getText().toString(), + cont.getText().toString(), + pkg.getText().toString(), + cls.getText().toString(), + act.isChecked() ? WapPushManagerParams.APP_TYPE_ACTIVITY : + WapPushManagerParams.APP_TYPE_SERVICE, + sig.isChecked(), ftr.isChecked())) { + + Log.w(LOG_TAG, "remote add pkg failed..."); + mWapPushMan.updatePackage( + app_id.getText().toString(), + cont.getText().toString(), + pkg.getText().toString(), + cls.getText().toString(), + act.isChecked() ? WapPushManagerParams.APP_TYPE_ACTIVITY : + WapPushManagerParams.APP_TYPE_SERVICE, + sig.isChecked(), ftr.isChecked()); + } + } catch (RemoteException e) { + Log.w(LOG_TAG, "remote func failed..."); + } + } + }); + + delbtn.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + EditText app_id = (EditText) findViewById(R.id.app_id); + EditText cont = (EditText) findViewById(R.id.cont); + EditText pkg = (EditText) findViewById(R.id.pkg); + EditText cls = (EditText) findViewById(R.id.cls); + // CheckBox delall = (CheckBox) findViewById(R.id.delall); + // Log.d(LOG_TAG, "button clicked"); + + try { + mWapPushMan.deletePackage( + app_id.getText().toString(), + cont.getText().toString(), + pkg.getText().toString(), + cls.getText().toString()); + // delall.isChecked()); + } catch (RemoteException e) { + Log.w(LOG_TAG, "remote func failed..."); + } + } + }); + + procbtn.setOnClickListener(new View.OnClickListener() { + public void onClick(View v) { + EditText pdu = (EditText) findViewById(R.id.pdu); + EditText app_id = (EditText) findViewById(R.id.app_id); + EditText cont = (EditText) findViewById(R.id.cont); + + // WapPushOverSms wap = new WapPushOverSms(); + // wap.dispatchWapPdu(strToHex(pdu.getText().toString())); + try { + Intent intent = new Intent(); + intent.putExtra("transactionId", 0); + intent.putExtra("pduType", 6); + intent.putExtra("header", + HexDump.hexStringToByteArray(pdu.getText().toString())); + intent.putExtra("data", + HexDump.hexStringToByteArray(pdu.getText().toString())); + + mWapPushMan.processMessage( + app_id.getText().toString(), + cont.getText().toString(), + intent); + //HexDump.hexStringToByteArray(pdu.getText().toString()), 0, 6, 5, 5); + } catch (RemoteException e) { + Log.w(LOG_TAG, "remote func failed..."); + } + } + }); + } + + private IWapPushManager mWapPushMan; + private ServiceConnection conn = new ServiceConnection() { + public void onServiceDisconnected(ComponentName name) { + mWapPushMan = null; + Log.v(LOG_TAG, "service disconnected."); + } + + public void onServiceConnected(ComponentName name, IBinder service) { + mWapPushMan = IWapPushManager.Stub.asInterface(service); + Log.v(LOG_TAG, "service connected."); + } + }; + + @Override + public void onStart() { + super.onStart(); + Log.v(LOG_TAG, "onStart bind WAPPushManager service " + + IWapPushManager.class.getName()); + this.bindService(new Intent(IWapPushManager.class.getName()), conn, + Context.BIND_AUTO_CREATE); + Log.v(LOG_TAG, "bind service done."); + } + + @Override + public void onDestroy() { + super.onDestroy(); + this.unbindService(conn); + } + +} diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/DataVerify.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/DataVerify.java new file mode 100644 index 000000000000..ef491fda0d46 --- /dev/null +++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/DataVerify.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.smspush.unitTests; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; + +import com.android.internal.util.HexDump; + +/** + * To verify that receiver application receives correct body data. + */ +public class DataVerify extends Service { + private static final String LOG_TAG = "WAP PUSH"; + private static final int TIME_WAIT = 100; + private static final int WAIT_COUNT = 100; + private static byte[] mLastReceivedPdu = null; + private static boolean sDataSet = false; + + private class IDataVerifyStub extends IDataVerify.Stub { + public Context mContext; + + public IDataVerifyStub() { + } + + boolean arrayCompare(byte[] arr1, byte[] arr2) { + int i; + + if (arr1 == null || arr2 == null) { + if (arr1 == null) { + Log.w(LOG_TAG, "arr1 is null"); + } else { + Log.w(LOG_TAG, "arr2 is null"); + } + return false; + } + + if (arr1.length != arr2.length) { + return false; + } + + for (i = 0; i < arr1.length; i++) { + if (arr1[i] != arr2[i]) return false; + } + return true; + } + + /** + * Compare pdu and received pdu + */ + public synchronized boolean verifyData(byte[] pdu) { + int cnt = 0; + + while (!sDataSet) { + // wait for the activity receive data. + try { + Thread.sleep(TIME_WAIT); + if (cnt++ > WAIT_COUNT) { + // don't wait more than 10 sec. + return false; + } + } catch (InterruptedException e) {} + } + + Log.v(LOG_TAG, "verify pdu"); + boolean ret = arrayCompare(pdu, mLastReceivedPdu); + return ret; + } + + /** + * Clear the old data. This method must be called before starting the test + */ + public void resetData() { + mLastReceivedPdu = null; + sDataSet = false; + } + } + + private final IDataVerifyStub binder = new IDataVerifyStub(); + + /** + * Constructor + */ + public DataVerify() { + } + + /** + * Receiver application must call this method when it receives the wap push message + */ + public static void SetLastReceivedPdu(byte[] pdu) { + mLastReceivedPdu = pdu; + sDataSet = true; + } + + @Override + public IBinder onBind(Intent arg0) { + return binder; + } + +} + + diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/DrmReceiver.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/DrmReceiver.java new file mode 100644 index 000000000000..5f5f121e4194 --- /dev/null +++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/DrmReceiver.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.smspush.unitTests; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import com.android.internal.util.HexDump; + +/** + * A sample wap push receiver application for existing framework + * This class is listening for "application/vnd.oma.drm.rights+xml" message + */ +public class DrmReceiver extends BroadcastReceiver { + private static final String LOG_TAG = "WAP PUSH"; + + @Override + public void onReceive(Context context, Intent intent) { + Log.d(LOG_TAG, "DrmReceiver received."); + + byte[] body; + byte[] header; + + body = intent.getByteArrayExtra("data"); + header = intent.getByteArrayExtra("header"); + + Log.d(LOG_TAG, "header:"); + Log.d(LOG_TAG, HexDump.dumpHexString(header)); + Log.d(LOG_TAG, "body:"); + Log.d(LOG_TAG, HexDump.dumpHexString(body)); + + DataVerify.SetLastReceivedPdu(body); + } + +} + + diff --git a/libs/rs/java/HelloCompute/src/com/android/example/hellocompute/mono.rs b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/IDataVerify.aidl index 9647c612f1cf..f0670fa2eefd 100644 --- a/libs/rs/java/HelloCompute/src/com/android/example/hellocompute/mono.rs +++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/IDataVerify.aidl @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Android Open Source Project + * Copyright (C) 2010 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. @@ -14,23 +14,20 @@ * limitations under the License. */ -#pragma version(1) -#pragma rs java_package_name(com.android.example.hellocompute) +package com.android.smspush.unitTests; -rs_allocation gIn; -rs_allocation gOut; -rs_script gScript; - -const static float3 gMonoMult = {0.299f, 0.587f, 0.114f}; - -void root(const uchar4 *v_in, uchar4 *v_out, const void *usrData, uint32_t x, uint32_t y) { - float4 f4 = rsUnpackColor8888(*v_in); - - float3 mono = dot(f4.rgb, gMonoMult); - *v_out = rsPackColorTo8888(mono); -} +/** + * Interface to receiver application data verifyer class + */ +interface IDataVerify { + /** + * Verify data + */ + boolean verifyData(in byte[] pdu); -void filter() { - rsForEach(gScript, gIn, gOut, 0); + /** + * Initialize data + */ + void resetData(); } diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ReceiverActivity.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ReceiverActivity.java new file mode 100644 index 000000000000..07f55eaae237 --- /dev/null +++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ReceiverActivity.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.smspush.unitTests; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; + +import com.android.internal.util.HexDump; + +/** + * Activity type receiver application + */ +public class ReceiverActivity extends Activity { + private static final String LOG_TAG = "WAP PUSH"; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d(LOG_TAG, "activity created!!"); + + Intent in = getIntent(); + byte[] body; + byte[] header; + + body = in.getByteArrayExtra("data"); + header = in.getByteArrayExtra("header"); + + Log.d(LOG_TAG, "header:"); + Log.d(LOG_TAG, HexDump.dumpHexString(header)); + Log.d(LOG_TAG, "body:"); + Log.d(LOG_TAG, HexDump.dumpHexString(body)); + + DataVerify.SetLastReceivedPdu(body); + + finish(); + + } +} + diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ReceiverService.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ReceiverService.java new file mode 100644 index 000000000000..b024bf5802ec --- /dev/null +++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/ReceiverService.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.smspush.unitTests; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.IBinder; +import android.util.Log; + +import com.android.internal.util.HexDump; + +/** + * Service type receiver application + */ +public class ReceiverService extends Service { + private static final String LOG_TAG = "WAP PUSH"; + + @Override + public void onCreate() { + super.onCreate(); + Log.d(LOG_TAG, "Receiver service created"); + } + + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Log.d(LOG_TAG, "Receiver service started"); + + byte[] body; + byte[] header; + body = intent.getByteArrayExtra("data"); + header = intent.getByteArrayExtra("header"); + + Log.d(LOG_TAG, "header:"); + Log.d(LOG_TAG, HexDump.dumpHexString(header)); + Log.d(LOG_TAG, "body:"); + Log.d(LOG_TAG, HexDump.dumpHexString(body)); + + DataVerify.SetLastReceivedPdu(body); + return START_STICKY; + } +} + + diff --git a/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/WapPushTest.java b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/WapPushTest.java new file mode 100644 index 000000000000..9b0a36b37181 --- /dev/null +++ b/packages/WAPPushManager/tests/src/com/android/smspush/unitTests/WapPushTest.java @@ -0,0 +1,2513 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.smspush.unitTests; + +import android.app.Activity; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; +import android.os.RemoteException; +import android.provider.Telephony.Sms.Intents; +import android.test.ServiceTestCase; +import android.util.Log; +import android.util.Config; + +import com.android.internal.telephony.IccUtils; +import com.android.internal.telephony.IWapPushManager; +import com.android.internal.telephony.WapPushManagerParams; +import com.android.internal.telephony.WspTypeDecoder; +import com.android.internal.util.HexDump; +import com.android.smspush.WapPushManager; + +import java.util.Random; + +/** + * This is a simple framework for a test of a Service. See {@link android.test.ServiceTestCase + * ServiceTestCase} for more information on how to write and extend service tests. + * + * To run this test, you can type: + * adb shell am instrument -w \ + * -e class com.android.smspush.unitTests.WapPushTest \ + * com.android.smspush.unitTests/android.test.InstrumentationTestRunner + */ +public class WapPushTest extends ServiceTestCase<WapPushManager> { + private static final String LOG_TAG = "WAP PUSH"; + private static final boolean LOCAL_LOGV = false; + private static final int TIME_WAIT = 100; + + protected int mAppIdValue = 0x8002; + protected String mAppIdName = "x-wap-application:*"; + protected int mContentTypeValue = 0x030a; + protected String mContentTypeName = "application/vnd.wap.sic"; + + protected String mPackageName; + protected String mClassName; + + protected byte[] mGsmHeader = { + (byte) 0x00, // sc address + (byte) 0x40, // TP-MTI + (byte) 0x04, // sender address length? + (byte) 0x81, (byte) 0x55, (byte) 0x45, // sender address? + (byte) 0x00, // data schema + (byte) 0x00, // proto ID + (byte) 0x01, (byte) 0x60, (byte) 0x12, (byte) 0x31, + (byte) 0x74, (byte) 0x34, (byte) 0x63 // time stamp + }; + + protected byte[] mUserDataHeader = { + (byte) 0x07, // UDH len + (byte) 0x06, // header len + (byte) 0x05, // port addressing type? + (byte) 0x00, // dummy + (byte) 0x0B, (byte) 0x84, // dest port + (byte) 0x23, (byte) 0xF0 // src port + }; + + protected byte[] mWspHeader; + + protected byte[] mMessageBody = { + (byte) 0x00, + (byte) 0x01, + (byte) 0x02, + (byte) 0x03, + (byte) 0x04, + (byte) 0x05, + (byte) 0x06, + (byte) 0x07, + (byte) 0x08, + (byte) 0x09, + (byte) 0x0a, + (byte) 0x0b, + (byte) 0x0c, + (byte) 0x0d, + (byte) 0x0e, + (byte) 0x0f + }; + + protected int mWspHeaderStart; + protected int mWspHeaderLen; + protected int mWspContentTypeStart; + + /** + * OMA application ID in binary form + * http://www.openmobilealliance.org/tech/omna/omna-push-app-id.aspx + */ + final int[] OMA_APPLICATION_ID_VALUES = new int[] { + 0x00, + 0x01, + 0x02, + 0x03, + 0x04, + 0x05, + 0x06, + 0x07, + 0x08, + 0x09, + 0x0A, + 0x8000, + 0x8001, + 0x8002, + 0x8003, + 0x8004, + 0x8005, + 0x8006, + 0x8007, + 0x8008, + 0x8009, + 0x800B, + 0x8010 + }; + + /** + * OMA application ID in string form + * http://www.openmobilealliance.org/tech/omna/omna-push-app-id.aspx + */ + final String[] OMA_APPLICATION_ID_NAMES = new String[] { + "x-wap-application:*", + "x-wap-application:push.sia", + "x-wap-application:wml.ua", + "x-wap-application:wta.ua", + "x-wap-application:mms.ua", + "x-wap-application:push.syncml", + "x-wap-application:loc.ua", + "x-wap-application:syncml.dm", + "x-wap-application:drm.ua", + "x-wap-application:emn.ua", + "x-wap-application:wv.ua", + "x-wap-microsoft:localcontent.ua", + "x-wap-microsoft:IMclient.ua", + "x-wap-docomo:imode.mail.ua", + "x-wap-docomo:imode.mr.ua", + "x-wap-docomo:imode.mf.ua", + "x-motorola:location.ua", + "x-motorola:now.ua", + "x-motorola:otaprov.ua", + "x-motorola:browser.ua", + "x-motorola:splash.ua", + "x-wap-nai:mvsw.command", + "x-wap-openwave:iota.ua" + }; + + /** + * OMA content type in binary form + * http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx + */ + final int[] OMA_CONTENT_TYPE_VALUES = new int[] { + 0x00, + 0x01, + 0x02, + 0x03, + 0x04, + 0x05, + 0x06, + 0x07, + 0x08, + 0x09, + 0x0A, + 0x0B, + 0x0C, + 0x0D, + 0x0E, + 0x0F, + 0x10, + 0x11, + 0x12, + 0x13, + 0x14, + 0x15, + 0x16, + 0x17, + 0x18, + 0x19, + 0x1A, + 0x1B, + 0x1C, + 0x1D, + 0x1E, + 0x1F, + 0x20, + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, + 0x26, + 0x27, + 0x28, + 0x29, + 0x2A, + 0x2B, + 0x2C, + 0x2D, + 0x2E, + 0x2F, + 0x30, + 0x31, + 0x32, + 0x33, + 0x34, + 0x35, + 0x36, + 0x37, + 0x38, + 0x39, + 0x3A, + 0x3B, + 0x3C, + 0x3D, + 0x3E, + 0x3F, + 0x40, + 0x41, + 0x42, + 0x43, + 0x44, + 0x45, + 0x46, + 0x47, + 0x48, + 0x49, + 0x4A, + 0x4B, + 0x4C, + 0x4D, + 0x4E, + 0x4F, + 0x50, + 0x51, + 0x52, + 0x53, + 0x54, +// 0x55, +// 0x56, +// 0x57, +// 0x58, + 0x0201, + 0x0202, + 0x0203, + 0x0204, + 0x0205, + 0x0206, + 0x0207, + 0x0208, + 0x0209, + 0x020A, + 0x020B, + 0x020C, + 0x0300, + 0x0301, + 0x0302, + 0x0303, + 0x0304, + 0x0305, + 0x0306, + 0x0307, + 0x0308, + 0x0309, + 0x030A, + 0x030B, + 0x030C, + 0x030D, + 0x030E, + 0x030F, + 0x0310, + 0x0311, + 0x0312, + 0x0313, + 0x0314, + 0x0315, + 0x0316, + 0x0317, + 0x0318, + 0x0319, + 0x031A, + 0x031B + /*0x031C, + 0x031D*/ + }; + + /** + * OMA content type in string form + * http://www.openmobilealliance.org/tech/omna/omna-wsp-content-type.aspx + */ + final String[] OMA_CONTENT_TYPE_NAMES = new String[] { + "*/*", + "text/*", + "text/html", + "text/plain", + "text/x-hdml", + "text/x-ttml", + "text/x-vCalendar", + "text/x-vCard", + "text/vnd.wap.wml", + "text/vnd.wap.wmlscript", + "text/vnd.wap.wta-event", + "multipart/*", + "multipart/mixed", + "multipart/form-data", + "multipart/byterantes", + "multipart/alternative", + "application/*", + "application/java-vm", + "application/x-www-form-urlencoded", + "application/x-hdmlc", + "application/vnd.wap.wmlc", + "application/vnd.wap.wmlscriptc", + "application/vnd.wap.wta-eventc", + "application/vnd.wap.uaprof", + "application/vnd.wap.wtls-ca-certificate", + "application/vnd.wap.wtls-user-certificate", + "application/x-x509-ca-cert", + "application/x-x509-user-cert", + "image/*", + "image/gif", + "image/jpeg", + "image/tiff", + "image/png", + "image/vnd.wap.wbmp", + "application/vnd.wap.multipart.*", + "application/vnd.wap.multipart.mixed", + "application/vnd.wap.multipart.form-data", + "application/vnd.wap.multipart.byteranges", + "application/vnd.wap.multipart.alternative", + "application/xml", + "text/xml", + "application/vnd.wap.wbxml", + "application/x-x968-cross-cert", + "application/x-x968-ca-cert", + "application/x-x968-user-cert", + "text/vnd.wap.si", + "application/vnd.wap.sic", + "text/vnd.wap.sl", + "application/vnd.wap.slc", + "text/vnd.wap.co", + "application/vnd.wap.coc", + "application/vnd.wap.multipart.related", + "application/vnd.wap.sia", + "text/vnd.wap.connectivity-xml", + "application/vnd.wap.connectivity-wbxml", + "application/pkcs7-mime", + "application/vnd.wap.hashed-certificate", + "application/vnd.wap.signed-certificate", + "application/vnd.wap.cert-response", + "application/xhtml+xml", + "application/wml+xml", + "text/css", + "application/vnd.wap.mms-message", + "application/vnd.wap.rollover-certificate", + "application/vnd.wap.locc+wbxml", + "application/vnd.wap.loc+xml", + "application/vnd.syncml.dm+wbxml", + "application/vnd.syncml.dm+xml", + "application/vnd.syncml.notification", + "application/vnd.wap.xhtml+xml", + "application/vnd.wv.csp.cir", + "application/vnd.oma.dd+xml", + "application/vnd.oma.drm.message", + "application/vnd.oma.drm.content", + "application/vnd.oma.drm.rights+xml", + "application/vnd.oma.drm.rights+wbxml", + "application/vnd.wv.csp+xml", + "application/vnd.wv.csp+wbxml", + "application/vnd.syncml.ds.notification", + "audio/*", + "video/*", + "application/vnd.oma.dd2+xml", + "application/mikey", + "application/vnd.oma.dcd", + "application/vnd.oma.dcdc", +// "text/x-vMessage", +// "application/vnd.omads-email+wbxml", +// "text/x-vBookmark", +// "application/vnd.syncml.dm.notification", + "application/vnd.uplanet.cacheop-wbxml", + "application/vnd.uplanet.signal", + "application/vnd.uplanet.alert-wbxml", + "application/vnd.uplanet.list-wbxml", + "application/vnd.uplanet.listcmd-wbxml", + "application/vnd.uplanet.channel-wbxml", + "application/vnd.uplanet.provisioning-status-uri", + "x-wap.multipart/vnd.uplanet.header-set", + "application/vnd.uplanet.bearer-choice-wbxml", + "application/vnd.phonecom.mmc-wbxml", + "application/vnd.nokia.syncset+wbxml", + "image/x-up-wpng", + "application/iota.mmc-wbxml", + "application/iota.mmc-xml", + "application/vnd.syncml+xml", + "application/vnd.syncml+wbxml", + "text/vnd.wap.emn+xml", + "text/calendar", + "application/vnd.omads-email+xml", + "application/vnd.omads-file+xml", + "application/vnd.omads-folder+xml", + "text/directory;profile=vCard", + "application/vnd.wap.emn+wbxml", + "application/vnd.nokia.ipdc-purchase-response", + "application/vnd.motorola.screen3+xml", + "application/vnd.motorola.screen3+gzip", + "application/vnd.cmcc.setting+wbxml", + "application/vnd.cmcc.bombing+wbxml", + "application/vnd.docomo.pf", + "application/vnd.docomo.ub", + "application/vnd.omaloc-supl-init", + "application/vnd.oma.group-usage-list+xml", + "application/oma-directory+xml", + "application/vnd.docomo.pf2", + "application/vnd.oma.drm.roap-trigger+wbxml", + "application/vnd.sbm.mid2", + "application/vnd.wmf.bootstrap", + "application/vnc.cmcc.dcd+xml", + "application/vnd.sbm.cid", + "application/vnd.oma.bcast.provisioningtrigger", + /*"application/vnd.docomo.dm", + "application/vnd.oma.scidm.messages+xml"*/ + }; + + private IDataVerify mIVerify = null; + + ServiceConnection mConn = new ServiceConnection() { + public void onServiceConnected(ComponentName name, IBinder service) { + Log.v(LOG_TAG, "data verify interface connected."); + mIVerify = IDataVerify.Stub.asInterface(service); + } + public void onServiceDisconnected(ComponentName name) { + } + }; + + /** + * Main WapPushManager test module constructor + */ + public WapPushTest() { + super(WapPushManager.class); + mClassName = this.getClass().getName(); + mPackageName = this.getClass().getPackage().getName(); + } + + /** + * Initialize the verifier + */ + @Override + public void setUp() { + try { + super.setUp(); + // get verifier + getContext().bindService(new Intent(IDataVerify.class.getName()), + mConn, Context.BIND_AUTO_CREATE); + } catch (Exception e) { + Log.w(LOG_TAG, "super exception"); + } + // Log.d(LOG_TAG, "test setup"); + } + + private IWapPushManager mWapPush = null; + IWapPushManager getInterface() { + if (mWapPush != null) return mWapPush; + Intent startIntent = new Intent(); + startIntent.setClass(getContext(), WapPushManager.class); + IBinder service = bindService(startIntent); + + mWapPush = IWapPushManager.Stub.asInterface(service); + return mWapPush; + } + + /* + * All methods need to start with 'test'. + * Use various assert methods to pass/fail the test case. + */ + protected void utAddPackage(boolean need_sig, boolean more_proc) { + IWapPushManager iwapman = getInterface(); + + // insert new data + try { + assertTrue(iwapman.addPackage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, need_sig, more_proc)); + } catch (RemoteException e) { + assertTrue(false); + } + + // verify the data + WapPushManager wpman = getService(); + assertTrue(wpman.verifyData(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, need_sig, more_proc)); + } + + /** + * Add package test + */ + public void testAddPackage1() { + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + + utAddPackage(true, true); + mAppIdValue += 10; + utAddPackage(true, false); + mContentTypeValue += 20; + utAddPackage(false, true); + mContentTypeValue += 20; + utAddPackage(false, false); + + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + + // clean up data + try { + IWapPushManager iwapman = getInterface(); + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + mAppIdValue += 10; + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + mContentTypeValue += 20; + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + mContentTypeValue += 20; + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + } catch (RemoteException e) { + assertTrue(false); + } + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + } + + /** + * Add duprecated package test. + */ + public void testAddPackage2() { + try { + IWapPushManager iwapman = getInterface(); + + // set up data + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, 0, + false, false); + iwapman.addPackage(Integer.toString(mAppIdValue + 10), + Integer.toString(mContentTypeValue), mPackageName, mClassName, 0, + false, false); + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue + 10), mPackageName, mClassName, 0, + false, false); + + assertFalse(iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, 0, + false, false)); + assertFalse(iwapman.addPackage(Integer.toString(mAppIdValue + 10), + Integer.toString(mContentTypeValue), mPackageName, mClassName, 0, + false, false)); + assertFalse(iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue + 10), mPackageName, mClassName, 0, + false, false)); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + iwapman.deletePackage(Integer.toString(mAppIdValue + 10), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue + 10), mPackageName, mClassName); + } catch (RemoteException e) { + assertTrue(false); + } + } + + protected void utUpdatePackage(boolean need_sig, boolean more_proc) { + IWapPushManager iwapman = getInterface(); + + // insert new data + try { + assertTrue(iwapman.updatePackage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, need_sig, more_proc)); + } catch (RemoteException e) { + assertTrue(false); + } + + // verify the data + WapPushManager wpman = getService(); + assertTrue(wpman.verifyData( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, need_sig, more_proc)); + } + + /** + * Updating package test + */ + public void testUpdatePackage1() { + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + + // set up data + try { + IWapPushManager iwapman = getInterface(); + + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + mAppIdValue += 10; + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + mContentTypeValue += 20; + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + mContentTypeValue += 20; + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + } catch (RemoteException e) { + assertTrue(false); + } + + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + utUpdatePackage(false, false); + mAppIdValue += 10; + utUpdatePackage(false, true); + mContentTypeValue += 20; + utUpdatePackage(true, false); + mContentTypeValue += 20; + utUpdatePackage(true, true); + + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + + // clean up data + try { + IWapPushManager iwapman = getInterface(); + + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + mAppIdValue += 10; + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + mContentTypeValue += 20; + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + mContentTypeValue += 20; + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + } catch (RemoteException e) { + assertTrue(false); + } + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + } + + /** + * Updating invalid package test + */ + public void testUpdatePackage2() { + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + + try { + // set up data + IWapPushManager iwapman = getInterface(); + + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + assertFalse(iwapman.updatePackage( + Integer.toString(mAppIdValue + 10), + Integer.toString(mContentTypeValue), + mPackageName, mClassName, 0, false, false)); + assertFalse(iwapman.updatePackage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue + 10), + mPackageName, mClassName, 0, false, false)); + assertTrue(iwapman.updatePackage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName + "dummy_data", mClassName, 0, false, false)); + assertTrue(iwapman.updatePackage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName, mClassName + "dummy_data", 0, false, false)); + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, + mClassName + "dummy_data"); + } catch (RemoteException e) { + assertTrue(false); + } + } + + protected void utDeletePackage() { + IWapPushManager iwapman = getInterface(); + + try { + assertTrue(iwapman.deletePackage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName, mClassName)); + } catch (RemoteException e) { + assertTrue(false); + } + + // verify the data + WapPushManager wpman = getService(); + assertTrue(!wpman.isDataExist( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + mPackageName, mClassName)); + } + + /** + * Deleting package test + */ + public void testDeletePackage1() { + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + + // set up data + try { + IWapPushManager iwapman = getInterface(); + + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + mAppIdValue += 10; + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + mContentTypeValue += 20; + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + mContentTypeValue += 20; + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + } catch (RemoteException e) { + assertTrue(false); + } + + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + utDeletePackage(); + mAppIdValue += 10; + utDeletePackage(); + mContentTypeValue += 20; + utDeletePackage(); + mContentTypeValue += 20; + utDeletePackage(); + + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + } + + /** + * Deleting invalid package test + */ + public void testDeletePackage2() { + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + + try { + // set up data + IWapPushManager iwapman = getInterface(); + + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + 0, false, false); + + assertFalse(iwapman.deletePackage(Integer.toString(mAppIdValue + 10), + Integer.toString(mContentTypeValue), mPackageName, mClassName)); + assertFalse(iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue + 20), mPackageName, mClassName)); + assertFalse(iwapman.deletePackage(Integer.toString(mAppIdValue + 10), + Integer.toString(mContentTypeValue + 20), mPackageName, mClassName)); + + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + } catch (RemoteException e) { + assertTrue(false); + } + } + + + protected int encodeUint32(int uint32Val, byte[] arr, int start) { + int bit = 1; + int topbit = 0; + int encodeLen; + int tmpVal; + + assertTrue(uint32Val >= 0); + for (int i = 0; i < 31; i++) { + if ((bit & uint32Val) > 0) topbit = i; + bit = (bit << 1); + } + encodeLen = topbit/7 + 1; + if (arr == null) return encodeLen; + + //Log.d(LOG_TAG, "uint32Val = " + Integer.toHexString(uint32Val) + ", topbit = " + // + topbit + ", encodeLen = " + encodeLen); + + tmpVal = uint32Val; + for (int i = encodeLen - 1; i >= 0; i--) { + long val = 0; + if (i < encodeLen - 1) val = 0x80; + val |= tmpVal & 0x7f; + arr[start + i] = (byte) (val & 0xFF); + tmpVal = (tmpVal >> 7); + } + return encodeLen; + } + + protected int encodeShortInt(int sintVal, byte[] arr, int start) { + int encodeLen = 0; + + if (sintVal >= 0x80) return encodeLen; + encodeLen = 1; + arr[start] = (byte) (sintVal | 0x80); + return encodeLen; + } + + + /** + * Generate Random WSP header with integer application ID + */ + protected void createRandomWspHeader(byte[] arr, Random rd, int headerStart, + boolean noAppId) { + + boolean appIdAdded = false; + + Log.d(LOG_TAG, "headerStart = " + headerStart + ", appId = " + mAppIdValue + + "(" + Integer.toHexString(mAppIdValue) + ")"); + Log.d(LOG_TAG, "random arr length:" + arr.length); + String typename[] = new String[] { "short int", "long int", "string", "uint32"}; + + while (!appIdAdded) { + int type; + int index = headerStart; + int len = arr.length; + int i; + boolean addAppid = false; + int tmpVal = 0; + int tmpVal2 = 0; + + while (true) { + int add; + + /* + * field name + * 0: short int + * 1: long int + * 2: text + * (no uint for param value) + */ + type = rd.nextInt(3); + switch (type) { + case 0: // header short integer + if (index > 100 && !appIdAdded) addAppid = true; + add = 1; + break; + case 1: // header long int + add = 1 + rd.nextInt(29); + break; + default: // header string + add = 2 + rd.nextInt(10); + break; + } + if (index + add >= len) break; + + // fill header name + switch (type) { + case 0: // header short integer + if (!addAppid) { + do { + arr[index] = (byte) (0x80 | rd.nextInt(128)); + } while (arr[index] == (byte) 0xaf); + } else { + Log.d(LOG_TAG, "appId added."); + arr[index] = (byte) 0xaf; + // if noAppId case, appId fld must be decieved. + if (noAppId) arr[index]++; + } + break; + case 1: // header long int + arr[index] = (byte) (add - 1); + tmpVal2 = 0; + for (i = 1; i < add; i++) { + tmpVal = rd.nextInt(255); + tmpVal2 = (tmpVal2 << 8) | tmpVal; + arr[index + i] = (byte) tmpVal; + } + // don't set application id + if (tmpVal2 == 0x2f) arr[index + 1]++; + break; + default: // header string + for (i = 0; i < add - 1; i++) { + tmpVal = rd.nextInt(127); + if (tmpVal < 32) tmpVal= (32 + tmpVal); + arr[index + i] = (byte) tmpVal; + } + arr[index + i] = (byte) 0x0; + break; + } + + if (LOCAL_LOGV) { + Log.d(LOG_TAG, "field name index:" + index); + Log.d(LOG_TAG, "type:" + typename[type] + ", add:" + add); + if (type != 2) { + for (i = index; i< index + add; i++) { + System.out.print(Integer.toHexString(0xff & arr[i])); + System.out.print(' '); + } + } else { + System.out.print(Integer.toHexString(0xff & arr[index])); + System.out.print(' '); + String str = new String(arr, index + 1, add - 2); + for (i = 0; i < str.length(); i++) { + System.out.print(str.charAt(i)); + System.out.print(' '); + } + } + System.out.print('\n'); + } + index += add; + + + /* + * field value + * 0: short int + * 1: long int + * 2: text + * 3: uint + */ + if (addAppid) { + type = 1; + } else { + type = rd.nextInt(4); + } + switch (type) { + case 0: // header short integer + add = 1; + break; + case 1: // header long int + if (addAppid) { + int bit = 1; + int topBit = 0; + + for (i = 0; i < 31; i++) { + if ((mAppIdValue & bit) > 0) topBit = i; + bit = (bit << 1); + } + add = 2 + topBit/8; + } else { + add = 1 + rd.nextInt(29); + } + break; + case 2: // header string + add = 2 + rd.nextInt(10); + break; + default: // uint32 + add = 6; + } + if (index + add >= len) break; + + // fill field value + switch (type) { + case 0: // header short int + arr[index] = (byte) (0x80 | rd.nextInt(128)); + break; + case 1: // header long int + if (addAppid) { + addAppid = false; + appIdAdded = true; + + arr[index] = (byte) (add - 1); + tmpVal = mAppIdValue; + for (i = add; i > 1; i--) { + arr[index + i - 1] = (byte) (tmpVal & 0xff); + tmpVal = (tmpVal >> 8); + } + } else { + arr[index] = (byte) (add - 1); + for (i = 1; i < add; i++) { + arr[index + i] = (byte) rd.nextInt(255); + } + } + break; + case 2:// header string + for (i = 0; i < add - 1; i++) { + tmpVal = rd.nextInt(127); + if (tmpVal < 32) tmpVal= (32 + tmpVal); + arr[index + i] = (byte) tmpVal; + } + arr[index + i] = (byte) 0x0; + break; + default: // header uvarint + arr[index] = (byte) 31; + tmpVal = rd.nextInt(0x0FFFFFFF); + add = 1 + encodeUint32(tmpVal, null, index + 1); + encodeUint32(tmpVal, arr, index + 1); + break; + + } + + if (LOCAL_LOGV) { + Log.d(LOG_TAG, "field value index:" + index); + Log.d(LOG_TAG, "type:" + typename[type] + ", add:" + add); + if (type != 2) { + for (i = index; i< index + add; i++) { + System.out.print(Integer.toHexString(0xff & arr[i])); + System.out.print(' '); + } + } else { + System.out.print(Integer.toHexString(0xff & arr[index])); + System.out.print(' '); + String str = new String(arr, index + 1, add - 2); + for (i = 0; i < str.length(); i++) { + System.out.print(str.charAt(i)); + System.out.print(' '); + } + } + System.out.print('\n'); + } + index += add; + } + if (noAppId) break; + } + + Log.d(LOG_TAG, HexDump.dumpHexString(arr)); + } + + /** + * Generate Random WSP header with string application ID + */ + protected void createRandomWspHeaderStrAppId(byte[] arr, Random rd, int headerStart, + boolean randomStr) { + + boolean appIdAdded = false; + + Log.d(LOG_TAG, "random arr length:" + arr.length); + String typename[] = new String[] { "short int", "long int", "string", "uint32"}; + + while (!appIdAdded) { + int type; + int index = headerStart; + int len = arr.length; + int i; + boolean addAppid = false; + int tmpVal = 0; + int tmpVal2 = 0; + + while (true) { + int add; + + /* + * field name + * 0: short int + * 1: long int + * 2: text + * (no uint for param value) + */ + type = rd.nextInt(3); + switch (type) { + case 0: // header short integer + if (index > 100 && !appIdAdded) addAppid = true; + add = 1; + break; + case 1: // header long int + add = 1 + rd.nextInt(29); + break; + default: // header string + add = 2 + rd.nextInt(10); + break; + } + if (index + add >= len) break; + + // fill header name + switch (type) { + case 0: // header short integer + if (!addAppid) { + do { + arr[index] = (byte) (0x80 | rd.nextInt(128)); + } while (arr[index] == (byte) 0xaf); + } else { + Log.d(LOG_TAG, "appId added."); + arr[index] = (byte) 0xaf; + } + break; + case 1: // header long int + arr[index] = (byte) (add - 1); + tmpVal2 = 0; + for (i = 1; i < add; i++) { + tmpVal = rd.nextInt(255); + tmpVal2 = (tmpVal2 << 8) | tmpVal; + arr[index + i] = (byte) tmpVal; + } + // don't set application id + if (tmpVal2 == 0x2f) arr[index + 1]++; + break; + default: // header string + for (i = 0; i < add - 1; i++) { + tmpVal = rd.nextInt(127); + if (tmpVal < 32) tmpVal= (32 + tmpVal); + arr[index + i] = (byte) tmpVal; + } + arr[index + i] = (byte) 0x0; + break; + } + + if (LOCAL_LOGV) { + Log.d(LOG_TAG, "field name index:" + index); + Log.d(LOG_TAG, "type:" + typename[type] + ", add:" + add); + if (type != 2) { + for (i = index; i < index + add; i++) { + System.out.print(Integer.toHexString(0xff & arr[i])); + System.out.print(' '); + } + } else { + System.out.print(Integer.toHexString(0xff & arr[index])); + System.out.print(' '); + String str = new String(arr, index + 1, add - 2); + for (i = 0; i < str.length(); i++) { + System.out.print(str.charAt(i)); + System.out.print(' '); + } + } + System.out.print('\n'); + } + index += add; + + + /* + * field value + * 0: short int + * 1: long int + * 2: text + * 3: uint + */ + if (addAppid) { + type = 2; + } else { + type = rd.nextInt(4); + } + switch (type) { + case 0: // header short integer + add = 1; + break; + case 1: // header long int + add = 1 + rd.nextInt(29); + break; + case 2: // header string + if (addAppid) { + if (randomStr) { + add = 1 + rd.nextInt(10); + byte[] randStr= new byte[add]; + for (i = 0; i < add; i++) { + tmpVal = rd.nextInt(127); + if (tmpVal < 32) tmpVal= (32 + tmpVal); + randStr[i] = (byte) tmpVal; + } + mAppIdName = new String(randStr); + } + add = mAppIdName.length() + 1; + } else { + add = 2 + rd.nextInt(10); + } + break; + default: // uint32 + add = 6; + } + if (index + add >= len) break; + + // fill field value + switch (type) { + case 0: // header short int + arr[index] = (byte) (0x80 | rd.nextInt(128)); + break; + case 1: // header long int + arr[index] = (byte) (add - 1); + for (i = 1; i < add; i++) + arr[index + i] = (byte) rd.nextInt(255); + break; + case 2:// header string + if (addAppid) { + addAppid = false; + appIdAdded = true; + for (i = 0; i < add - 1; i++) { + arr[index + i] = (byte) (mAppIdName.charAt(i)); + } + Log.d(LOG_TAG, "mAppIdName added [" + mAppIdName + "]"); + } else { + for (i = 0; i < add - 1; i++) { + tmpVal = rd.nextInt(127); + if (tmpVal < 32) tmpVal= (32 + tmpVal); + arr[index + i] = (byte) tmpVal; + } + } + arr[index + i] = (byte) 0x0; + break; + default: // header uvarint + arr[index] = (byte) 31; + tmpVal = rd.nextInt(0x0FFFFFFF); + add = 1 + encodeUint32(tmpVal, null, index + 1); + encodeUint32(tmpVal, arr, index + 1); + break; + + } + + if (LOCAL_LOGV) { + Log.d(LOG_TAG, "field value index:" + index); + Log.d(LOG_TAG, "type:" + typename[type] + ", add:" + add); + if (type != 2) { + for (i = index; i < index + add; i++) { + System.out.print(Integer.toHexString(0xff & arr[i])); + System.out.print(' '); + } + } else { + System.out.print(Integer.toHexString(0xff & arr[index])); + System.out.print(' '); + String str = new String(arr, index + 1, add - 2); + for (i = 0; i < str.length(); i++) { + System.out.print(str.charAt(i)); + System.out.print(' '); + } + } + System.out.print('\n'); + } + index += add; + } + } + + Log.d(LOG_TAG, "headerStart = " + headerStart + ", mAppIdName = " + mAppIdName); + Log.d(LOG_TAG, HexDump.dumpHexString(arr)); + } + + protected byte[] createPDU(int testNum) { + byte[] array = null; + // byte[] wsp = null; + + switch (testNum) { + // sample pdu + case 1: + byte[] array1 = { + (byte) 0x00, // TID + (byte) 0x06, // Type = wap push + (byte) 0x00, // Length to be set later. + + // Content-Type + (byte) 0x03, (byte) 0x02, + (byte) ((mContentTypeValue >> 8) & 0xff), + (byte) (mContentTypeValue & 0xff), + + // Application-id + (byte) 0xaf, (byte) 0x02, + (byte) ((mAppIdValue >> 8) & 0xff), + (byte) (mAppIdValue& 0xff) + }; + array1[2] = (byte) (array1.length - 3); + mWspHeader = array1; + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length + 7; + mWspHeaderLen = array1.length; + break; + + // invalid wsp header + case 2: + byte[] array2 = { + (byte) 0x00, // invalid data + }; + mWspHeader = array2; + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length; + mWspHeaderLen = array2.length; + break; + + // random wsp header + case 3: + Random rd = new Random(); + int arrSize = 150 + rd.nextInt(100); + byte[] array3 = new byte[arrSize]; + int hdrEncodeLen; + + array3[0] = (byte) 0x0; + array3[1] = (byte) 0x6; + hdrEncodeLen = encodeUint32(array3.length, null, 2); + hdrEncodeLen = encodeUint32(array3.length - hdrEncodeLen - 2, array3, 2); + array3[hdrEncodeLen + 2] = (byte) 0x3; + array3[hdrEncodeLen + 3] = (byte) 0x2; + array3[hdrEncodeLen + 4] = (byte) ((mContentTypeValue >> 8) & 0xff); + array3[hdrEncodeLen + 5] = (byte) (mContentTypeValue & 0xff); + createRandomWspHeader(array3, rd, hdrEncodeLen + 6, false); + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length + hdrEncodeLen + 6; + mWspHeaderLen = array3.length; + + Log.d(LOG_TAG, "mContentTypeValue = " + mContentTypeValue + + "(" + Integer.toHexString(mContentTypeValue) + ")"); + + mWspHeader = array3; + break; + + // random wsp header w/o appid + case 4: + rd = new Random(); + arrSize = 150 + rd.nextInt(100); + array3 = new byte[arrSize]; + + array3[0] = (byte) 0x0; + array3[1] = (byte) 0x6; + hdrEncodeLen = encodeUint32(array3.length, null, 2); + hdrEncodeLen = encodeUint32(array3.length - hdrEncodeLen - 2, array3, 2); + array3[hdrEncodeLen + 2] = (byte) 0x3; + array3[hdrEncodeLen + 3] = (byte) 0x2; + array3[hdrEncodeLen + 4] = (byte) ((mContentTypeValue >> 8) & 0xff); + array3[hdrEncodeLen + 5] = (byte) (mContentTypeValue & 0xff); + createRandomWspHeader(array3, rd, hdrEncodeLen + 6, true); + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length + hdrEncodeLen + 6; + mWspHeaderLen = array3.length; + + Log.d(LOG_TAG, "mContentTypeValue = " + mContentTypeValue + + "(" + Integer.toHexString(mContentTypeValue) + ")"); + + mWspHeader = array3; + break; + + // random wsp header w/ random appid string + case 5: + rd = new Random(); + arrSize = 150 + rd.nextInt(100); + array3 = new byte[arrSize]; + + array3[0] = (byte) 0x0; + array3[1] = (byte) 0x6; + hdrEncodeLen = encodeUint32(array3.length, null, 2); + hdrEncodeLen = encodeUint32(array3.length - hdrEncodeLen - 2, array3, 2); + array3[hdrEncodeLen + 2] = (byte) 0x3; + array3[hdrEncodeLen + 3] = (byte) 0x2; + array3[hdrEncodeLen + 4] = (byte) ((mContentTypeValue >> 8) & 0xff); + array3[hdrEncodeLen + 5] = (byte) (mContentTypeValue & 0xff); + createRandomWspHeaderStrAppId(array3, rd, hdrEncodeLen + 6, true); + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length + hdrEncodeLen + 6; + mWspHeaderLen = array3.length; + + Log.d(LOG_TAG, "mContentTypeValue = " + mContentTypeValue + + "(" + Integer.toHexString(mContentTypeValue) + ")"); + + mWspHeader = array3; + break; + + // random wsp header w/ OMA appid string + case 6: + rd = new Random(); + arrSize = 150 + rd.nextInt(100); + array3 = new byte[arrSize]; + + array3[0] = (byte) 0x0; + array3[1] = (byte) 0x6; + hdrEncodeLen = encodeUint32(array3.length, null, 2); + hdrEncodeLen = encodeUint32(array3.length - hdrEncodeLen - 2, array3, 2); + array3[hdrEncodeLen + 2] = (byte) 0x3; + array3[hdrEncodeLen + 3] = (byte) 0x2; + array3[hdrEncodeLen + 4] = (byte) ((mContentTypeValue >> 8) & 0xff); + array3[hdrEncodeLen + 5] = (byte) (mContentTypeValue & 0xff); + createRandomWspHeaderStrAppId(array3, rd, hdrEncodeLen + 6, false); + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length + hdrEncodeLen + 6; + mWspHeaderLen = array3.length; + + Log.d(LOG_TAG, "mContentTypeValue = " + mContentTypeValue + + "(" + Integer.toHexString(mContentTypeValue) + ")"); + + mWspHeader = array3; + break; + + // random wsp header w/ OMA content type + case 7: + rd = new Random(); + arrSize = 150 + rd.nextInt(100); + array3 = new byte[arrSize]; + + array3[0] = (byte) 0x0; + array3[1] = (byte) 0x6; + hdrEncodeLen = encodeUint32(array3.length, null, 2); + hdrEncodeLen = encodeUint32(array3.length - hdrEncodeLen - 2, array3, 2); + + // encode content type + int contentLen = mContentTypeName.length(); + int next = 2 + hdrEncodeLen; + mWspContentTypeStart = mGsmHeader.length + mUserDataHeader.length + next; + // next += encodeUint32(contentLen, array3, next); + int i; + Log.d(LOG_TAG, "mContentTypeName = " + mContentTypeName + + ", contentLen = " + contentLen); + + for (i = 0; i < contentLen; i++) { + array3[next + i] = (byte) mContentTypeName.charAt(i); + } + array3[next + i] = (byte) 0x0; + + createRandomWspHeader(array3, rd, next + contentLen + 1, false); + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length + + next + contentLen + 1; + mWspHeaderLen = array3.length; + + mWspHeader = array3; + break; + + // random wsp header w/ OMA content type, OMA app ID + case 8: + rd = new Random(); + arrSize = 150 + rd.nextInt(100); + array3 = new byte[arrSize]; + + array3[0] = (byte) 0x0; + array3[1] = (byte) 0x6; + hdrEncodeLen = encodeUint32(array3.length, null, 2); + hdrEncodeLen = encodeUint32(array3.length - hdrEncodeLen - 2, array3, 2); + + // encode content type + contentLen = mContentTypeName.length(); + next = 2 + hdrEncodeLen; + mWspContentTypeStart = mGsmHeader.length + mUserDataHeader.length + next; + // next += encodeUint32(contentLen, array3, next); + Log.d(LOG_TAG, "mContentTypeName = " + mContentTypeName + + ", contentLen = " + contentLen); + + for (i = 0; i < contentLen; i++) { + array3[next + i] = (byte) mContentTypeName.charAt(i); + } + array3[next + i] = (byte) 0x0; + + createRandomWspHeaderStrAppId(array3, rd, next + contentLen + 1, false); + mWspHeaderStart = mGsmHeader.length + mUserDataHeader.length + + next + contentLen + 1; + mWspHeaderLen = array3.length; + + mWspHeader = array3; + break; + + default: + return null; + } + array = new byte[mGsmHeader.length + mUserDataHeader.length + mWspHeader.length + + mMessageBody.length]; + System.arraycopy(mGsmHeader, 0, array, 0, mGsmHeader.length); + System.arraycopy(mUserDataHeader, 0, array, + mGsmHeader.length, mUserDataHeader.length); + System.arraycopy(mWspHeader, 0, array, + mGsmHeader.length + mUserDataHeader.length, mWspHeader.length); + System.arraycopy(mMessageBody, 0, array, + mGsmHeader.length + mUserDataHeader.length + mWspHeader.length, + mMessageBody.length); + return array; + + } + + Intent createIntent(int pduType, int tranId) { + Intent intent = new Intent(); + intent.putExtra("transactionId", tranId); + intent.putExtra("pduType", pduType); + intent.putExtra("header", mGsmHeader); + intent.putExtra("data", mMessageBody); + // intent.putExtra("contentTypeParameters", null); + return intent; + } + + /** + * Message processing test, start activity + */ + public void testProcessMsg1() { + byte[] pdu = createPDU(1); + int headerLen = pdu.length - + (mGsmHeader.length + mUserDataHeader.length + mMessageBody.length); + int pduType = 6; + int tranId = 0; + String originalPackageName = mPackageName; + String originalClassName = mClassName; + + try { + + mClassName = "com.android.smspush.unitTests.ReceiverActivity"; + + // set up data + IWapPushManager iwapman = getInterface(); + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_ACTIVITY, false, false); + + assertTrue((iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)) + & WapPushManagerParams.MESSAGE_HANDLED) == + WapPushManagerParams.MESSAGE_HANDLED); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + } catch (RemoteException e) { + assertTrue(false); + } + + mPackageName = originalPackageName; + mClassName = originalClassName; + } + + /** + * Message processing test, start service + */ + public void testProcessMsg2() { + byte[] pdu = createPDU(1); + int headerLen = pdu.length - (mGsmHeader.length + + mUserDataHeader.length + mMessageBody.length); + int pduType = 6; + int tranId = 0; + String originalPackageName = mPackageName; + String originalClassName = mClassName; + + try { + + mClassName = "com.android.smspush.unitTests.ReceiverService"; + + // set up data + IWapPushManager iwapman = getInterface(); + + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, false, false); + + assertTrue((iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)) + & WapPushManagerParams.MESSAGE_HANDLED) == + WapPushManagerParams.MESSAGE_HANDLED); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + } catch (RemoteException e) { + assertTrue(false); + } + + mPackageName = originalPackageName; + mClassName = originalClassName; + } + + /** + * Message processing test, no signature + */ + public void testProcessMsg3() { + byte[] pdu = createPDU(1); + int headerLen = pdu.length - + (mGsmHeader.length + mUserDataHeader.length + mMessageBody.length); + int pduType = 6; + int tranId = 0; + String originalPackageName = mPackageName; + String originalClassName = mClassName; + + try { + + mPackageName = "com.android.development"; + mClassName = "com.android.development.Development"; + + // set up data + IWapPushManager iwapman = getInterface(); + + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, true, false); + + assertFalse((iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)) + & WapPushManagerParams.MESSAGE_HANDLED) == + WapPushManagerParams.MESSAGE_HANDLED); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + } catch (RemoteException e) { + assertTrue(false); + } + + mPackageName = originalPackageName; + mClassName = originalClassName; + } + + IDataVerify getVerifyInterface() { + while (mIVerify == null) { + // wait for the activity receive data. + try { + Thread.sleep(TIME_WAIT); + } catch (InterruptedException e) {} + } + return mIVerify; + } + + + /** + * Message processing test, received body data verification test + */ + public void testProcessMsg4() { + byte[] originalMessageBody = mMessageBody; + mMessageBody = new byte[] { + (byte) 0xee, + (byte) 0xff, + (byte) 0xee, + (byte) 0xff, + (byte) 0xee, + (byte) 0xff, + (byte) 0xee, + (byte) 0xff, + (byte) 0xee, + (byte) 0xff, + (byte) 0xee, + (byte) 0xff, + }; + + byte[] pdu = createPDU(1); + int headerLen = pdu.length - + (mGsmHeader.length + mUserDataHeader.length + mMessageBody.length); + int pduType = 6; + int tranId = 0; + String originalPackageName = mPackageName; + String originalClassName = mClassName; + + try { + IWapPushManager iwapman = getInterface(); + IDataVerify dataverify = getVerifyInterface(); + + dataverify.resetData(); + + // set up data + mClassName = "com.android.smspush.unitTests.ReceiverActivity"; + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_ACTIVITY, false, false); + + iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + assertTrue(dataverify.verifyData(mMessageBody)); + + // set up data + dataverify.resetData(); + mClassName = "com.android.smspush.unitTests.ReceiverService"; + mMessageBody = new byte[] { + (byte) 0xaa, + (byte) 0xbb, + (byte) 0x11, + (byte) 0x22, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0x11, + (byte) 0x22, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0x11, + (byte) 0x22, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0x11, + (byte) 0x22, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0x11, + (byte) 0x22, + (byte) 0xaa, + (byte) 0xbb, + (byte) 0x11, + (byte) 0x22, + }; + pdu = createPDU(1); + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, false, false); + + iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + // Log.d(LOG_TAG, HexDump.dumpHexString(mMessageBody)); + assertTrue(dataverify.verifyData(mMessageBody)); + } catch (RemoteException e) { + assertTrue(false); + } + + mPackageName = originalPackageName; + mClassName = originalClassName; + mMessageBody = originalMessageBody; + } + + /** + * Message processing test, send invalid sms data + */ + public void testProcessMsg5() { + byte[] pdu = createPDU(2); + int headerLen = pdu.length - + (mGsmHeader.length + mUserDataHeader.length + mMessageBody.length); + int pduType = 6; + int tranId = 0; + String originalPackageName = mPackageName; + String originalClassName = mClassName; + + try { + + mClassName = "com.android.smspush.unitTests.ReceiverActivity"; + + // set up data + IWapPushManager iwapman = getInterface(); + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_ACTIVITY, false, false); + + assertTrue((iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)) + & WapPushManagerParams.MESSAGE_HANDLED) == + WapPushManagerParams.MESSAGE_HANDLED); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + } catch (RemoteException e) { + assertTrue(false); + } + + mPackageName = originalPackageName; + mClassName = originalClassName; + } + + /** + * Message processing test, no receiver application + */ + public void testProcessMsg6() { + byte[] pdu = createPDU(1); + int headerLen = pdu.length - + (mGsmHeader.length + mUserDataHeader.length + mMessageBody.length); + int pduType = 6; + int tranId = 0; + String originalPackageName = mPackageName; + String originalClassName = mClassName; + + try { + + mClassName = "com.android.smspush.unitTests.NoReceiver"; + + // set up data + IWapPushManager iwapman = getInterface(); + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_ACTIVITY, false, false); + + assertFalse((iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)) + & WapPushManagerParams.MESSAGE_HANDLED) == + WapPushManagerParams.MESSAGE_HANDLED); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + // set up data + iwapman.addPackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, false, false); + + assertFalse((iwapman.processMessage( + Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), + createIntent(pduType, tranId)) + & WapPushManagerParams.MESSAGE_HANDLED) == + WapPushManagerParams.MESSAGE_HANDLED); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + Integer.toString(mContentTypeValue), mPackageName, mClassName); + + } catch (RemoteException e) { + assertTrue(false); + } + + mPackageName = originalPackageName; + mClassName = originalClassName; + } + + /** + * WspTypeDecoder test, normal pdu + */ + public void testDecoder1() { + boolean res; + int originalAppIdValue = mAppIdValue; + Random rd = new Random(); + + for (int i = 0; i < 10; i++) { + mAppIdValue = rd.nextInt(0xFFFF); + byte[] pdu = createPDU(1); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + res = pduDecoder.seekXWapApplicationId(mWspHeaderStart, + mWspHeaderStart + mWspHeaderLen - 1); + assertTrue(res); + + int index = (int) pduDecoder.getValue32(); + res = pduDecoder.decodeXWapApplicationId(index); + assertTrue(res); + + Log.d(LOG_TAG, "mAppIdValue: " + mAppIdValue + + ", val: " + pduDecoder.getValue32()); + assertTrue(mAppIdValue == (int) pduDecoder.getValue32()); + } + + mAppIdValue = originalAppIdValue; + } + + /** + * WspTypeDecoder test, no header + */ + public void testDecoder2() { + boolean res; + int originalAppIdValue = mAppIdValue; + Random rd = new Random(); + + mAppIdValue = rd.nextInt(0xFFFF); + byte[] pdu = createPDU(2); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + res = pduDecoder.seekXWapApplicationId(mWspHeaderStart, + mWspHeaderStart + mWspHeaderLen - 1); + assertFalse(res); + + mAppIdValue = originalAppIdValue; + } + + /** + * WspTypeDecoder test, decode appid test + */ + public void testDecoder3() { + boolean res; + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + Random rd = new Random(); + + for (int i = 0; i < 100; i++) { + mAppIdValue = rd.nextInt(0x0FFFFFFF); + mContentTypeValue = rd.nextInt(0x0FFF); + byte[] pdu = createPDU(3); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + res = pduDecoder.seekXWapApplicationId(mWspHeaderStart, + mWspHeaderStart + mWspHeaderLen - 1); + assertTrue(res); + + int index = (int) pduDecoder.getValue32(); + res = pduDecoder.decodeXWapApplicationId(index); + assertTrue(res); + + Log.d(LOG_TAG, "mAppIdValue: " + mAppIdValue + + ", val: " + pduDecoder.getValue32()); + assertTrue(mAppIdValue == (int) pduDecoder.getValue32()); + } + + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + } + + /* + public void testEnc() { + byte[] arr = new byte[20]; + int index = 0; + index += encodeUint32(0x87a5, arr, index); + index += encodeUint32(0x1, arr, index); + index += encodeUint32(0x9b, arr, index); + index += encodeUint32(0x10, arr, index); + index += encodeUint32(0xe0887, arr, index); + index += encodeUint32(0x791a23d0, arr, index); + + Log.d(LOG_TAG, HexDump.dumpHexString(arr)); + } + */ + + /** + * WspTypeDecoder test, no appid test + */ + public void testDecoder4() { + boolean res; + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + Random rd = new Random(); + + for (int i = 0; i < 100; i++) { + mAppIdValue = rd.nextInt(0x0FFFFFFF); + mContentTypeValue = rd.nextInt(0x0FFF); + byte[] pdu = createPDU(4); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + res = pduDecoder.seekXWapApplicationId(mWspHeaderStart, + mWspHeaderStart + mWspHeaderLen - 1); + assertFalse(res); + + } + + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + } + + /** + * WspTypeDecoder test, decode string appid test + */ + public void testDecoder5() { + boolean res; + String originalAppIdName = mAppIdName; + int originalContentTypeValue = mContentTypeValue; + Random rd = new Random(); + + for (int i = 0; i < 10; i++) { + mAppIdValue = rd.nextInt(0x0FFFFFFF); + mContentTypeValue = rd.nextInt(0x0FFF); + byte[] pdu = createPDU(5); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + res = pduDecoder.seekXWapApplicationId(mWspHeaderStart, + mWspHeaderStart + mWspHeaderLen - 1); + assertTrue(res); + + int index = (int) pduDecoder.getValue32(); + res = pduDecoder.decodeXWapApplicationId(index); + assertTrue(res); + + Log.d(LOG_TAG, "mAppIdValue: [" + mAppIdName + "], val: [" + + pduDecoder.getValueString() + "]"); + assertTrue(mAppIdName.equals(pduDecoder.getValueString())); + } + + mAppIdName = originalAppIdName; + mContentTypeValue = originalContentTypeValue; + } + + /** + * WspTypeDecoder test, decode string appid test + */ + public void testDecoder6() { + boolean res; + String originalAppIdName = mAppIdName; + int originalContentTypeValue = mContentTypeValue; + Random rd = new Random(); + + for (int i = 0; i < OMA_APPLICATION_ID_NAMES.length; i++) { + mAppIdName = OMA_APPLICATION_ID_NAMES[i]; + mContentTypeValue = rd.nextInt(0x0FFF); + byte[] pdu = createPDU(6); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + res = pduDecoder.seekXWapApplicationId(mWspHeaderStart, + mWspHeaderStart + mWspHeaderLen - 1); + assertTrue(res); + + int index = (int) pduDecoder.getValue32(); + res = pduDecoder.decodeXWapApplicationId(index); + assertTrue(res); + + Log.d(LOG_TAG, "mAppIdValue: [" + mAppIdName + "], val: [" + + pduDecoder.getValueString() + "]"); + assertTrue(mAppIdName.equals(pduDecoder.getValueString())); + } + + mAppIdName = originalAppIdName; + mContentTypeValue = originalContentTypeValue; + } + + /** + * WspTypeDecoder test, decode OMA content type + */ + public void testDecoder7() { + boolean res; + String originalAppIdName = mAppIdName; + int originalContentTypeValue = mContentTypeValue; + Random rd = new Random(); + + for (int i = 0; i < OMA_CONTENT_TYPE_NAMES.length; i++) { + mContentTypeName = OMA_CONTENT_TYPE_NAMES[i]; + byte[] pdu = createPDU(7); + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + res = pduDecoder.decodeContentType(mWspContentTypeStart); + assertTrue(res); + + Log.d(LOG_TAG, "mContentTypeName: [" + mContentTypeName + "], val: [" + + pduDecoder.getValueString() + "]"); + assertTrue(mContentTypeName.equals(pduDecoder.getValueString())); + } + + mAppIdName = originalAppIdName; + mContentTypeValue = originalContentTypeValue; + } + + + /** + * Copied from WapPushOverSms. + * The code flow is not changed from the original. + */ + public int dispatchWapPdu(byte[] pdu, IWapPushManager wapPushMan) { + + if (Config.DEBUG) Log.d(LOG_TAG, "Rx: " + IccUtils.bytesToHexString(pdu)); + + int index = 0; + int transactionId = pdu[index++] & 0xFF; + int pduType = pdu[index++] & 0xFF; + int headerLength = 0; + + if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) && + (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) { + if (Config.DEBUG) Log.w(LOG_TAG, "Received non-PUSH WAP PDU. Type = " + pduType); + return Intents.RESULT_SMS_HANDLED; + } + + WspTypeDecoder pduDecoder = new WspTypeDecoder(pdu); + + /** + * Parse HeaderLen(unsigned integer). + * From wap-230-wsp-20010705-a section 8.1.2 + * The maximum size of a uintvar is 32 bits. + * So it will be encoded in no more than 5 octets. + */ + if (pduDecoder.decodeUintvarInteger(index) == false) { + if (Config.DEBUG) Log.w(LOG_TAG, "Received PDU. Header Length error."); + return Intents.RESULT_SMS_GENERIC_ERROR; + } + headerLength = (int) pduDecoder.getValue32(); + index += pduDecoder.getDecodedDataLength(); + + int headerStartIndex = index; + + /** + * Parse Content-Type. + * From wap-230-wsp-20010705-a section 8.4.2.24 + * + * Content-type-value = Constrained-media | Content-general-form + * Content-general-form = Value-length Media-type + * Media-type = (Well-known-media | Extension-Media) *(Parameter) + * Value-length = Short-length | (Length-quote Length) + * Short-length = <Any octet 0-30> (octet <= WAP_PDU_SHORT_LENGTH_MAX) + * Length-quote = <Octet 31> (WAP_PDU_LENGTH_QUOTE) + * Length = Uintvar-integer + */ + if (pduDecoder.decodeContentType(index) == false) { + if (Config.DEBUG) Log.w(LOG_TAG, "Received PDU. Header Content-Type error."); + return Intents.RESULT_SMS_GENERIC_ERROR; + } + + String mimeType = pduDecoder.getValueString(); + long binaryContentType = pduDecoder.getValue32(); + index += pduDecoder.getDecodedDataLength(); + + byte[] header = new byte[headerLength]; + System.arraycopy(pdu, headerStartIndex, header, 0, header.length); + + byte[] intentData; + + if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { + intentData = pdu; + } else { + int dataIndex = headerStartIndex + headerLength; + intentData = new byte[pdu.length - dataIndex]; + System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length); + } + + /** + * Seek for application ID field in WSP header. + * If application ID is found, WapPushManager substitute the message + * processing. Since WapPushManager is optional module, if WapPushManager + * is not found, legacy message processing will be continued. + */ + if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) { + index = (int) pduDecoder.getValue32(); + pduDecoder.decodeXWapApplicationId(index); + String wapAppId = pduDecoder.getValueString(); + if (wapAppId == null) { + wapAppId = Integer.toString((int) pduDecoder.getValue32()); + } + + String contentType = ((mimeType == null) ? + Long.toString(binaryContentType) : mimeType); + if (Config.DEBUG) Log.v(LOG_TAG, "appid found: " + wapAppId + ":" + contentType); + + try { + boolean processFurther = true; + // IWapPushManager wapPushMan = mWapConn.getWapPushManager(); + if (wapPushMan == null) { + if (Config.DEBUG) Log.w(LOG_TAG, "wap push manager not found!"); + } else { + Intent intent = new Intent(); + intent.putExtra("transactionId", transactionId); + intent.putExtra("pduType", pduType); + intent.putExtra("header", header); + intent.putExtra("data", intentData); + intent.putExtra("contentTypeParameters", + pduDecoder.getContentParameters()); + + int procRet = wapPushMan.processMessage(wapAppId, contentType, intent); + if (Config.DEBUG) Log.v(LOG_TAG, "procRet:" + procRet); + if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0 + && (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) { + processFurther = false; + } + } + if (!processFurther) { + return Intents.RESULT_SMS_HANDLED; + } + } catch (RemoteException e) { + if (Config.DEBUG) Log.w(LOG_TAG, "remote func failed..."); + } + } + if (Config.DEBUG) Log.v(LOG_TAG, "fall back to existing handler"); + + return Activity.RESULT_OK; + } + + protected byte[] retrieveWspBody() { + byte[] array = new byte[mWspHeader.length + mMessageBody.length]; + + System.arraycopy(mWspHeader, 0, array, 0, mWspHeader.length); + System.arraycopy(mMessageBody, 0, array, mWspHeader.length, mMessageBody.length); + return array; + } + + protected String getContentTypeName(int ctypeVal) { + int i; + + for (i = 0; i < OMA_CONTENT_TYPE_VALUES.length; i++) { + if (ctypeVal == OMA_CONTENT_TYPE_VALUES[i]) { + return OMA_CONTENT_TYPE_NAMES[i]; + } + } + return null; + } + + protected boolean isContentTypeMapped(int ctypeVal) { + int i; + + for (i = 0; i < OMA_CONTENT_TYPE_VALUES.length; i++) { + if (ctypeVal == OMA_CONTENT_TYPE_VALUES[i]) return true; + } + return false; + } + + /** + * Integration test 1, simple case + */ + public void testIntegration1() { + boolean res; + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + String originalAppIdName = mAppIdName; + String originalContentTypeName = mContentTypeName; + String originalClassName = mClassName; + byte[] originalMessageBody = mMessageBody; + Random rd = new Random(); + + mMessageBody = new byte[100 + rd.nextInt(100)]; + rd.nextBytes(mMessageBody); + + byte[] pdu = createPDU(1); + byte[] wappushPdu = retrieveWspBody(); + + + mClassName = "com.android.smspush.unitTests.ReceiverActivity"; + // Phone dummy = new DummyPhone(getContext()); + // Phone gsm = PhoneFactory.getGsmPhone(); + // GSMPhone gsm = new GSMPhone(getContext(), new SimulatedCommands(), null, true); + // WapPushOverSms dispatcher = new WapPushOverSms(dummy, null); + + try { + // set up data + IWapPushManager iwapman = getInterface(); + IDataVerify dataverify = getVerifyInterface(); + + dataverify.resetData(); + + if (isContentTypeMapped(mContentTypeValue)) { + // content type is mapped + mContentTypeName = getContentTypeName(mContentTypeValue); + Log.d(LOG_TAG, "mContentTypeValue mapping " + + mContentTypeName + ":" + mContentTypeValue); + } else { + mContentTypeName = Integer.toString(mContentTypeValue); + } + iwapman.addPackage(Integer.toString(mAppIdValue), + mContentTypeName, mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_ACTIVITY, false, false); + + dispatchWapPdu(wappushPdu, iwapman); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + mContentTypeName, mPackageName, mClassName); + + assertTrue(dataverify.verifyData(mMessageBody)); + } catch (RemoteException e) { + } + + + mClassName = originalClassName; + mAppIdName = originalAppIdName; + mContentTypeName = originalContentTypeName; + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + mMessageBody = originalMessageBody; + } + + /** + * Integration test 2, random mAppIdValue(int), all OMA content type + */ + public void testIntegration2() { + boolean res; + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + String originalAppIdName = mAppIdName; + String originalContentTypeName = mContentTypeName; + String originalClassName = mClassName; + byte[] originalMessageBody = mMessageBody; + Random rd = new Random(); + + IWapPushManager iwapman = getInterface(); + IDataVerify dataverify = getVerifyInterface(); + mClassName = "com.android.smspush.unitTests.ReceiverActivity"; + + for (int i = 0; i < OMA_CONTENT_TYPE_NAMES.length; i++) { + mContentTypeName = OMA_CONTENT_TYPE_NAMES[i]; + mAppIdValue = rd.nextInt(0x0FFFFFFF); + + mMessageBody = new byte[100 + rd.nextInt(100)]; + rd.nextBytes(mMessageBody); + + byte[] pdu = createPDU(7); + byte[] wappushPdu = retrieveWspBody(); + + try { + dataverify.resetData(); + // set up data + iwapman.addPackage(Integer.toString(mAppIdValue), + mContentTypeName, mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_ACTIVITY, false, false); + + dispatchWapPdu(wappushPdu, iwapman); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + mContentTypeName, mPackageName, mClassName); + + if (mContentTypeName.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { + assertTrue(dataverify.verifyData(wappushPdu)); + } else { + assertTrue(dataverify.verifyData(mMessageBody)); + } + } catch (RemoteException e) { + } + } + + + mClassName = originalClassName; + mAppIdName = originalAppIdName; + mContentTypeName = originalContentTypeName; + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + mMessageBody = originalMessageBody; + } + + /** + * Integration test 3, iterate OmaApplication ID, random binary content type + */ + public void testIntegration3() { + boolean res; + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + String originalAppIdName = mAppIdName; + String originalContentTypeName = mContentTypeName; + String originalClassName = mClassName; + byte[] originalMessageBody = mMessageBody; + Random rd = new Random(); + + IWapPushManager iwapman = getInterface(); + IDataVerify dataverify = getVerifyInterface(); + mClassName = "com.android.smspush.unitTests.ReceiverService"; + + for (int i = 0; i < OMA_APPLICATION_ID_NAMES.length; i++) { + mAppIdName = OMA_APPLICATION_ID_NAMES[i]; + mContentTypeValue = rd.nextInt(0x0FFF); + + mMessageBody = new byte[100 + rd.nextInt(100)]; + rd.nextBytes(mMessageBody); + + byte[] pdu = createPDU(6); + byte[] wappushPdu = retrieveWspBody(); + + try { + dataverify.resetData(); + // set up data + if (isContentTypeMapped(mContentTypeValue)) { + // content type is mapped to integer value + mContentTypeName = getContentTypeName(mContentTypeValue); + Log.d(LOG_TAG, "mContentTypeValue mapping " + + mContentTypeValue + ":" + mContentTypeName); + } else { + mContentTypeName = Integer.toString(mContentTypeValue); + } + + iwapman.addPackage(mAppIdName, + mContentTypeName, mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, false, false); + + dispatchWapPdu(wappushPdu, iwapman); + + // clean up data + iwapman.deletePackage(mAppIdName, + mContentTypeName, mPackageName, mClassName); + + if (mContentTypeName.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { + assertTrue(dataverify.verifyData(wappushPdu)); + } else { + assertTrue(dataverify.verifyData(mMessageBody)); + } + } catch (RemoteException e) { + } + } + + mClassName = originalClassName; + mAppIdName = originalAppIdName; + mContentTypeName = originalContentTypeName; + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + mMessageBody = originalMessageBody; + } + + /** + * Integration test 4, iterate OmaApplication ID, Oma content type + */ + public void testIntegration4() { + boolean res; + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + String originalAppIdName = mAppIdName; + String originalContentTypeName = mContentTypeName; + String originalClassName = mClassName; + byte[] originalMessageBody = mMessageBody; + Random rd = new Random(); + + IWapPushManager iwapman = getInterface(); + IDataVerify dataverify = getVerifyInterface(); + mClassName = "com.android.smspush.unitTests.ReceiverService"; + + for (int i = 0; i < OMA_APPLICATION_ID_NAMES.length + + OMA_CONTENT_TYPE_NAMES.length; i++) { + mAppIdName = OMA_APPLICATION_ID_NAMES[rd.nextInt(OMA_APPLICATION_ID_NAMES.length)]; + int contIndex = rd.nextInt(OMA_CONTENT_TYPE_NAMES.length); + mContentTypeName = OMA_CONTENT_TYPE_NAMES[contIndex]; + + mMessageBody = new byte[100 + rd.nextInt(100)]; + rd.nextBytes(mMessageBody); + + byte[] pdu = createPDU(8); + byte[] wappushPdu = retrieveWspBody(); + + try { + dataverify.resetData(); + // set up data + iwapman.addPackage(mAppIdName, + mContentTypeName, mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, false, false); + + dispatchWapPdu(wappushPdu, iwapman); + + // clean up data + iwapman.deletePackage(mAppIdName, + mContentTypeName, mPackageName, mClassName); + + if (mContentTypeName.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { + assertTrue(dataverify.verifyData(wappushPdu)); + } else { + assertTrue(dataverify.verifyData(mMessageBody)); + } + } catch (RemoteException e) { + } + } + + mClassName = originalClassName; + mAppIdName = originalAppIdName; + mContentTypeName = originalContentTypeName; + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + mMessageBody = originalMessageBody; + } + + /** + * Integration test 5, iterate binary OmaApplication ID, Oma binary content type + */ + public void testIntegration5() { + boolean res; + int originalAppIdValue = mAppIdValue; + int originalContentTypeValue = mContentTypeValue; + String originalAppIdName = mAppIdName; + String originalContentTypeName = mContentTypeName; + String originalClassName = mClassName; + byte[] originalMessageBody = mMessageBody; + Random rd = new Random(); + + IWapPushManager iwapman = getInterface(); + IDataVerify dataverify = getVerifyInterface(); + mClassName = "com.android.smspush.unitTests.ReceiverService"; + + for (int i = 0; i < OMA_APPLICATION_ID_VALUES.length + + OMA_CONTENT_TYPE_VALUES.length; i++) { + mAppIdValue = OMA_APPLICATION_ID_VALUES[rd.nextInt( + OMA_APPLICATION_ID_VALUES.length)]; + mContentTypeValue = + OMA_CONTENT_TYPE_VALUES[rd.nextInt(OMA_CONTENT_TYPE_VALUES.length)]; + + mMessageBody = new byte[100 + rd.nextInt(100)]; + rd.nextBytes(mMessageBody); + + byte[] pdu = createPDU(3); + byte[] wappushPdu = retrieveWspBody(); + + try { + dataverify.resetData(); + // set up data + if (isContentTypeMapped(mContentTypeValue)) { + // content type is mapped to integer value + mContentTypeName = getContentTypeName(mContentTypeValue); + Log.d(LOG_TAG, "mContentTypeValue mapping " + + mContentTypeValue + ":" + mContentTypeName); + } else { + mContentTypeName = Integer.toString(mContentTypeValue); + } + + iwapman.addPackage(Integer.toString(mAppIdValue), + mContentTypeName, mPackageName, mClassName, + WapPushManagerParams.APP_TYPE_SERVICE, false, false); + + dispatchWapPdu(wappushPdu, iwapman); + + // clean up data + iwapman.deletePackage(Integer.toString(mAppIdValue), + mContentTypeName, mPackageName, mClassName); + + if (mContentTypeName.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { + assertTrue(dataverify.verifyData(wappushPdu)); + } else { + assertTrue(dataverify.verifyData(mMessageBody)); + } + } catch (RemoteException e) { + } + } + + mClassName = originalClassName; + mAppIdName = originalAppIdName; + mContentTypeName = originalContentTypeName; + mAppIdValue = originalAppIdValue; + mContentTypeValue = originalContentTypeValue; + mMessageBody = originalMessageBody; + } + +} diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp index 3082d45145a7..bfc80dbf4023 100644 --- a/services/audioflinger/AudioPolicyManagerBase.cpp +++ b/services/audioflinger/AudioPolicyManagerBase.cpp @@ -1889,7 +1889,15 @@ void AudioPolicyManagerBase::initializeVolumeCurves() { mStreams[i].mVolDbAtt[StreamDescriptor::VOLMAX] = 0.0f; } - // TODO add modifications for music to have finer steps below knee1 and above knee2 + // Modification for music: more attenuation for lower volumes, finer steps at high volumes + mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLMIN] = 1; + mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLMIN] = -58.0f; + mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLKNEE1] = 20; + mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLKNEE1] = -40.0f; + mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLKNEE2] = 60; + mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLKNEE2] = -17.0f; + mStreams[AudioSystem::MUSIC].mVolIndex[StreamDescriptor::VOLMAX] = 100; + mStreams[AudioSystem::MUSIC].mVolDbAtt[StreamDescriptor::VOLMAX] = 0.0f; } float AudioPolicyManagerBase::computeVolume(int stream, int index, audio_io_handle_t output, uint32_t device) diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index afa8d69c3596..f28e2b12ce55 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -1029,7 +1029,7 @@ class AppWidgetService extends IAppWidgetService.Stub com.android.internal.R.styleable.AppWidgetProviderInfo_previewImage, 0); info.autoAdvanceViewId = sa.getResourceId( com.android.internal.R.styleable.AppWidgetProviderInfo_autoAdvanceViewId, -1); - info.resizableMode = sa.getInt( + info.resizeMode = sa.getInt( com.android.internal.R.styleable.AppWidgetProviderInfo_resizeMode, AppWidgetProviderInfo.RESIZE_NONE); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 52c47e172ae9..d1609630646d 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -17,6 +17,7 @@ package com.android.server; import com.android.server.am.ActivityManagerService; +import com.android.server.usb.UsbService; import com.android.server.wm.WindowManagerService; import com.android.internal.app.ShutdownThread; import com.android.internal.os.BinderInternal; diff --git a/services/java/com/android/server/usb/UsbDeviceSettingsManager.java b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java new file mode 100644 index 000000000000..21eb7dcdcbf9 --- /dev/null +++ b/services/java/com/android/server/usb/UsbDeviceSettingsManager.java @@ -0,0 +1,861 @@ +/* + * 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.android.server.usb; + +import android.content.ActivityNotFoundException; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ResolveInfo; +import android.content.res.XmlResourceParser; +import android.hardware.UsbAccessory; +import android.hardware.UsbDevice; +import android.hardware.UsbInterface; +import android.hardware.UsbManager; +import android.os.Binder; +import android.os.FileUtils; +import android.os.Process; +import android.util.Log; +import android.util.SparseArray; +import android.util.Xml; + +import com.android.internal.content.PackageMonitor; +import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.XmlUtils; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +class UsbDeviceSettingsManager { + + private static final String TAG = "UsbDeviceSettingsManager"; + private static final File sSettingsFile = new File("/data/system/usb_device_manager.xml"); + + private final Context mContext; + + // maps UID to user approved USB devices + final SparseArray<ArrayList<DeviceFilter>> mDevicePermissionMap = + new SparseArray<ArrayList<DeviceFilter>>(); + // maps UID to user approved USB accessories + final SparseArray<ArrayList<AccessoryFilter>> mAccessoryPermissionMap = + new SparseArray<ArrayList<AccessoryFilter>>(); + // Maps DeviceFilter to user preferred application package + final HashMap<DeviceFilter, String> mDevicePreferenceMap = + new HashMap<DeviceFilter, String>(); + // Maps DeviceFilter to user preferred application package + final HashMap<AccessoryFilter, String> mAccessoryPreferenceMap = + new HashMap<AccessoryFilter, String>(); + + // This class is used to describe a USB device. + // When used in HashMaps all values must be specified, + // but wildcards can be used for any of the fields in + // the package meta-data. + private static class DeviceFilter { + // USB Vendor ID (or -1 for unspecified) + public final int mVendorId; + // USB Product ID (or -1 for unspecified) + public final int mProductId; + // USB device or interface class (or -1 for unspecified) + public final int mClass; + // USB device subclass (or -1 for unspecified) + public final int mSubclass; + // USB device protocol (or -1 for unspecified) + public final int mProtocol; + + public DeviceFilter(int vid, int pid, int clasz, int subclass, int protocol) { + mVendorId = vid; + mProductId = pid; + mClass = clasz; + mSubclass = subclass; + mProtocol = protocol; + } + + public DeviceFilter(UsbDevice device) { + mVendorId = device.getVendorId(); + mProductId = device.getProductId(); + mClass = device.getDeviceClass(); + mSubclass = device.getDeviceSubclass(); + mProtocol = device.getDeviceProtocol(); + } + + public static DeviceFilter read(XmlPullParser parser) + throws XmlPullParserException, IOException { + int vendorId = -1; + int productId = -1; + int deviceClass = -1; + int deviceSubclass = -1; + int deviceProtocol = -1; + + int count = parser.getAttributeCount(); + for (int i = 0; i < count; i++) { + String name = parser.getAttributeName(i); + // All attribute values are ints + int value = Integer.parseInt(parser.getAttributeValue(i)); + + if ("vendor-id".equals(name)) { + vendorId = value; + } else if ("product-id".equals(name)) { + productId = value; + } else if ("class".equals(name)) { + deviceClass = value; + } else if ("subclass".equals(name)) { + deviceSubclass = value; + } else if ("protocol".equals(name)) { + deviceProtocol = value; + } + } + return new DeviceFilter(vendorId, productId, + deviceClass, deviceSubclass, deviceProtocol); + } + + public void write(XmlSerializer serializer) throws IOException { + serializer.startTag(null, "usb-device"); + if (mVendorId != -1) { + serializer.attribute(null, "vendor-id", Integer.toString(mVendorId)); + } + if (mProductId != -1) { + serializer.attribute(null, "product-id", Integer.toString(mProductId)); + } + if (mClass != -1) { + serializer.attribute(null, "class", Integer.toString(mClass)); + } + if (mSubclass != -1) { + serializer.attribute(null, "subclass", Integer.toString(mSubclass)); + } + if (mProtocol != -1) { + serializer.attribute(null, "protocol", Integer.toString(mProtocol)); + } + serializer.endTag(null, "usb-device"); + } + + private boolean matches(int clasz, int subclass, int protocol) { + return ((mClass == -1 || clasz == mClass) && + (mSubclass == -1 || subclass == mSubclass) && + (mProtocol == -1 || protocol == mProtocol)); + } + + public boolean matches(UsbDevice device) { + if (mVendorId != -1 && device.getVendorId() != mVendorId) return false; + if (mProductId != -1 && device.getProductId() != mProductId) return false; + + // check device class/subclass/protocol + if (matches(device.getDeviceClass(), device.getDeviceSubclass(), + device.getDeviceProtocol())) return true; + + // if device doesn't match, check the interfaces + int count = device.getInterfaceCount(); + for (int i = 0; i < count; i++) { + UsbInterface intf = device.getInterface(i); + if (matches(intf.getInterfaceClass(), intf.getInterfaceSubclass(), + intf.getInterfaceProtocol())) return true; + } + + return false; + } + + @Override + public boolean equals(Object obj) { + // can't compare if we have wildcard strings + if (mVendorId == -1 || mProductId == -1 || + mClass == -1 || mSubclass == -1 || mProtocol == -1) { + return false; + } + if (obj instanceof DeviceFilter) { + DeviceFilter filter = (DeviceFilter)obj; + return (filter.mVendorId == mVendorId && + filter.mProductId == mProductId && + filter.mClass == mClass && + filter.mSubclass == mSubclass && + filter.mProtocol == mProtocol); + } + if (obj instanceof UsbDevice) { + UsbDevice device = (UsbDevice)obj; + return (device.getVendorId() == mVendorId && + device.getProductId() == mProductId && + device.getDeviceClass() == mClass && + device.getDeviceSubclass() == mSubclass && + device.getDeviceProtocol() == mProtocol); + } + return false; + } + + @Override + public int hashCode() { + return (((mVendorId << 16) | mProductId) ^ + ((mClass << 16) | (mSubclass << 8) | mProtocol)); + } + + @Override + public String toString() { + return "DeviceFilter[mVendorId=" + mVendorId + ",mProductId=" + mProductId + + ",mClass=" + mClass + ",mSubclass=" + mSubclass + + ",mProtocol=" + mProtocol + "]"; + } + } + + // This class is used to describe a USB accessory. + // When used in HashMaps all values must be specified, + // but wildcards can be used for any of the fields in + // the package meta-data. + private static class AccessoryFilter { + // USB accessory manufacturer (or null for unspecified) + public final String mManufacturer; + // USB accessory model (or null for unspecified) + public final String mModel; + // USB accessory type (or null for unspecified) + public final String mType; + // USB accessory version (or null for unspecified) + public final String mVersion; + + public AccessoryFilter(String manufacturer, String model, String type, String version) { + mManufacturer = manufacturer; + mModel = model; + mType = type; + mVersion = version; + } + + public AccessoryFilter(UsbAccessory accessory) { + mManufacturer = accessory.getManufacturer(); + mModel = accessory.getModel(); + mType = accessory.getType(); + mVersion = accessory.getVersion(); + } + + public static AccessoryFilter read(XmlPullParser parser) + throws XmlPullParserException, IOException { + String manufacturer = null; + String model = null; + String type = null; + String version = null; + + int count = parser.getAttributeCount(); + for (int i = 0; i < count; i++) { + String name = parser.getAttributeName(i); + String value = parser.getAttributeValue(i); + + if ("manufacturer".equals(name)) { + manufacturer = value; + } else if ("model".equals(name)) { + model = value; + } else if ("type".equals(name)) { + type = value; + } else if ("version".equals(name)) { + version = value; + } + } + return new AccessoryFilter(manufacturer, model, type, version); + } + + public void write(XmlSerializer serializer)throws IOException { + serializer.startTag(null, "usb-accessory"); + if (mManufacturer != null) { + serializer.attribute(null, "manufacturer", mManufacturer); + } + if (mModel != null) { + serializer.attribute(null, "model", mModel); + } + if (mType != null) { + serializer.attribute(null, "type", mType); + } + if (mVersion != null) { + serializer.attribute(null, "version", mVersion); + } + serializer.endTag(null, "usb-accessory"); + } + + public boolean matches(UsbAccessory acc) { + if (mManufacturer != null && !acc.getManufacturer().equals(mManufacturer)) return false; + if (mModel != null && !acc.getModel().equals(mModel)) return false; + if (mType != null && !acc.getType().equals(mType)) return false; + if (mVersion != null && !acc.getVersion().equals(mVersion)) return false; + return true; + } + + @Override + public boolean equals(Object obj) { + // can't compare if we have wildcard strings + if (mManufacturer == null || mModel == null || mType == null || mVersion == null) { + return false; + } + if (obj instanceof AccessoryFilter) { + AccessoryFilter filter = (AccessoryFilter)obj; + return (mManufacturer.equals(filter.mManufacturer) && + mModel.equals(filter.mModel) && + mType.equals(filter.mType) && + mVersion.equals(filter.mVersion)); + } + if (obj instanceof UsbAccessory) { + UsbAccessory accessory = (UsbAccessory)obj; + return (mManufacturer.equals(accessory.getManufacturer()) && + mModel.equals(accessory.getModel()) && + mType.equals(accessory.getType()) && + mVersion.equals(accessory.getVersion())); + } + return false; + } + + @Override + public int hashCode() { + return ((mManufacturer == null ? 0 : mManufacturer.hashCode()) ^ + (mModel == null ? 0 : mModel.hashCode()) ^ + (mType == null ? 0 : mType.hashCode()) ^ + (mVersion == null ? 0 : mVersion.hashCode())); + } + + @Override + public String toString() { + return "AccessoryFilter[mManufacturer=\"" + mManufacturer + + "\", mModel=\"" + mModel + + "\", mType=\"" + mType + + "\", mVersion=\"" + mVersion + "\"]"; + } + } + + private class MyPackageMonitor extends PackageMonitor { + public void onPackageRemoved(String packageName, int uid) { + // clear all activity preferences for the package + if (clearPackageDefaults(packageName)) { + writeSettings(); + } + } + + public void onUidRemoved(int uid) { + // clear all permissions for the UID + if (clearUidDefaults(uid)) { + writeSettings(); + } + } + } + MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); + + public UsbDeviceSettingsManager(Context context) { + mContext = context; + readSettings(); + mPackageMonitor.register(context, true); + } + + private void readDevicePermission(XmlPullParser parser) + throws XmlPullParserException, IOException { + int uid = -1; + ArrayList<DeviceFilter> filters = new ArrayList<DeviceFilter>(); + int count = parser.getAttributeCount(); + for (int i = 0; i < count; i++) { + if ("uid".equals(parser.getAttributeName(i))) { + uid = Integer.parseInt(parser.getAttributeValue(i)); + break; + } + } + XmlUtils.nextElement(parser); + while ("usb-device".equals(parser.getName())) { + filters.add(DeviceFilter.read(parser)); + XmlUtils.nextElement(parser); + } + mDevicePermissionMap.put(uid, filters); + } + + private void readAccessoryPermission(XmlPullParser parser) + throws XmlPullParserException, IOException { + int uid = -1; + ArrayList<AccessoryFilter> filters = new ArrayList<AccessoryFilter>(); + int count = parser.getAttributeCount(); + for (int i = 0; i < count; i++) { + if ("uid".equals(parser.getAttributeName(i))) { + uid = Integer.parseInt(parser.getAttributeValue(i)); + break; + } + } + XmlUtils.nextElement(parser); + while ("usb-accessory".equals(parser.getName())) { + filters.add(AccessoryFilter.read(parser)); + XmlUtils.nextElement(parser); + } + mAccessoryPermissionMap.put(uid, filters); + } + + private void readPreference(XmlPullParser parser) + throws XmlPullParserException, IOException { + String packageName = null; + int count = parser.getAttributeCount(); + for (int i = 0; i < count; i++) { + if ("package".equals(parser.getAttributeName(i))) { + packageName = parser.getAttributeValue(i); + break; + } + } + XmlUtils.nextElement(parser); + if ("usb-device".equals(parser.getName())) { + DeviceFilter filter = DeviceFilter.read(parser); + mDevicePreferenceMap.put(filter, packageName); + } else if ("usb-accessory".equals(parser.getName())) { + AccessoryFilter filter = AccessoryFilter.read(parser); + mAccessoryPreferenceMap.put(filter, packageName); + } + XmlUtils.nextElement(parser); + } + + private void readSettings() { + FileInputStream stream = null; + try { + stream = new FileInputStream(sSettingsFile); + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(stream, null); + + XmlUtils.nextElement(parser); + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + String tagName = parser.getName(); + if ("device-permission".equals(tagName)) { + readDevicePermission(parser); + } else if ("accessory-permission".equals(tagName)) { + readAccessoryPermission(parser); + } else if ("preference".equals(tagName)) { + readPreference(parser); + } else { + XmlUtils.nextElement(parser); + } + } + } catch (FileNotFoundException e) { + Log.w(TAG, "settings file not found"); + } catch (Exception e) { + Log.e(TAG, "error reading settings file, deleting to start fresh", e); + sSettingsFile.delete(); + } finally { + if (stream != null) { + try { + stream.close(); + } catch (IOException e) { + } + } + } + } + + private void writeSettings() { + FileOutputStream fos = null; + try { + FileOutputStream fstr = new FileOutputStream(sSettingsFile); + Log.d(TAG, "writing settings to " + fstr); + BufferedOutputStream str = new BufferedOutputStream(fstr); + FastXmlSerializer serializer = new FastXmlSerializer(); + serializer.setOutput(str, "utf-8"); + serializer.startDocument(null, true); + serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); + serializer.startTag(null, "settings"); + + int count = mDevicePermissionMap.size(); + for (int i = 0; i < count; i++) { + int uid = mDevicePermissionMap.keyAt(i); + ArrayList<DeviceFilter> filters = mDevicePermissionMap.valueAt(i); + serializer.startTag(null, "device-permission"); + serializer.attribute(null, "uid", Integer.toString(uid)); + int filterCount = filters.size(); + for (int j = 0; j < filterCount; j++) { + filters.get(j).write(serializer); + } + serializer.endTag(null, "device-permission"); + } + + count = mAccessoryPermissionMap.size(); + for (int i = 0; i < count; i++) { + int uid = mAccessoryPermissionMap.keyAt(i); + ArrayList<AccessoryFilter> filters = mAccessoryPermissionMap.valueAt(i); + serializer.startTag(null, "accessory-permission"); + serializer.attribute(null, "uid", Integer.toString(uid)); + int filterCount = filters.size(); + for (int j = 0; j < filterCount; j++) { + filters.get(j).write(serializer); + } + serializer.endTag(null, "accessory-permission"); + } + + for (DeviceFilter filter : mDevicePreferenceMap.keySet()) { + serializer.startTag(null, "preference"); + serializer.attribute(null, "package", mDevicePreferenceMap.get(filter)); + filter.write(serializer); + serializer.endTag(null, "preference"); + } + + for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) { + serializer.startTag(null, "preference"); + serializer.attribute(null, "package", mAccessoryPreferenceMap.get(filter)); + filter.write(serializer); + serializer.endTag(null, "preference"); + } + + serializer.endTag(null, "settings"); + serializer.endDocument(); + + str.flush(); + FileUtils.sync(fstr); + str.close(); + } catch (Exception e) { + Log.e(TAG, "error writing settings file, deleting to start fresh", e); + sSettingsFile.delete(); + } + } + + // Checks to see if a package matches a device or accessory. + // Only one of device and accessory should be non-null. + private boolean packageMatches(ResolveInfo info, String metaDataName, + UsbDevice device, UsbAccessory accessory) { + ActivityInfo ai = info.activityInfo; + PackageManager pm = mContext.getPackageManager(); + + XmlResourceParser parser = null; + try { + parser = ai.loadXmlMetaData(pm, metaDataName); + if (parser == null) { + Log.w(TAG, "no meta-data for " + info); + return false; + } + + XmlUtils.nextElement(parser); + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + String tagName = parser.getName(); + if (device != null && "usb-device".equals(tagName)) { + DeviceFilter filter = DeviceFilter.read(parser); + if (filter.matches(device)) { + return true; + } + } + else if (accessory != null && "usb-accessory".equals(tagName)) { + AccessoryFilter filter = AccessoryFilter.read(parser); + if (filter.matches(accessory)) { + return true; + } + } + XmlUtils.nextElement(parser); + } + } catch (Exception e) { + Log.w(TAG, "Unable to load component info " + info.toString(), e); + } finally { + if (parser != null) parser.close(); + } + return false; + } + + private final ArrayList<ResolveInfo> getDeviceMatches(UsbDevice device, Intent intent) { + ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>(); + PackageManager pm = mContext.getPackageManager(); + List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, + PackageManager.GET_META_DATA); + int count = resolveInfos.size(); + for (int i = 0; i < count; i++) { + ResolveInfo resolveInfo = resolveInfos.get(i); + if (packageMatches(resolveInfo, intent.getAction(), device, null)) { + matches.add(resolveInfo); + } + } + return matches; + } + + private final ArrayList<ResolveInfo> getAccessoryMatches(UsbAccessory accessory, Intent intent) { + ArrayList<ResolveInfo> matches = new ArrayList<ResolveInfo>(); + PackageManager pm = mContext.getPackageManager(); + List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, + PackageManager.GET_META_DATA); + int count = resolveInfos.size(); + for (int i = 0; i < count; i++) { + ResolveInfo resolveInfo = resolveInfos.get(i); + if (packageMatches(resolveInfo, intent.getAction(), null, accessory)) { + matches.add(resolveInfo); + } + } + return matches; + } + + public void deviceAttached(UsbDevice device) { + Intent deviceIntent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); + deviceIntent.putExtra(UsbManager.EXTRA_DEVICE, device); + deviceIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + ArrayList<ResolveInfo> matches = getDeviceMatches(device, deviceIntent); + // Launch our default activity directly, if we have one. + // Otherwise we will start the UsbResolverActivity to allow the user to choose. + String defaultPackage = mDevicePreferenceMap.get(new DeviceFilter(device)); + if (defaultPackage != null) { + int count = matches.size(); + for (int i = 0; i < count; i++) { + ResolveInfo rInfo = matches.get(i); + if (rInfo.activityInfo != null && + defaultPackage.equals(rInfo.activityInfo.packageName)) { + try { + deviceIntent.setComponent(new ComponentName( + defaultPackage, rInfo.activityInfo.name)); + mContext.startActivity(deviceIntent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "startActivity failed", e); + } + return; + } + } + } + + Intent intent = new Intent(mContext, UsbResolverActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + intent.putExtra(Intent.EXTRA_INTENT, deviceIntent); + intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, + matches); + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.w(TAG, "unable to start UsbResolverActivity"); + } + } + + public void deviceDetached(UsbDevice device) { + Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); + intent.putExtra(UsbManager.EXTRA_DEVICE, device); + Log.d(TAG, "usbDeviceRemoved, sending " + intent); + mContext.sendBroadcast(intent); + } + + public void accessoryAttached(UsbAccessory accessory) { + Intent accessoryIntent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); + accessoryIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + accessoryIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + ArrayList<ResolveInfo> matches = getAccessoryMatches(accessory, accessoryIntent); + // Launch our default activity directly, if we have one. + // Otherwise we will start the UsbResolverActivity to allow the user to choose. + String defaultPackage = mAccessoryPreferenceMap.get(new AccessoryFilter(accessory)); + if (defaultPackage != null) { + int count = matches.size(); + for (int i = 0; i < count; i++) { + ResolveInfo rInfo = matches.get(i); + if (rInfo.activityInfo != null && + defaultPackage.equals(rInfo.activityInfo.packageName)) { + try { + accessoryIntent.setComponent(new ComponentName( + defaultPackage, rInfo.activityInfo.name)); + mContext.startActivity(accessoryIntent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "startActivity failed", e); + } + return; + } + } + } + + Intent intent = new Intent(mContext, UsbResolverActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + + intent.putExtra(Intent.EXTRA_INTENT, accessoryIntent); + intent.putParcelableArrayListExtra(UsbResolverActivity.EXTRA_RESOLVE_INFOS, + matches); + try { + mContext.startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.w(TAG, "unable to start UsbResolverActivity"); + } + } + + public void accessoryDetached(UsbAccessory accessory) { + Intent intent = new Intent( + UsbManager.ACTION_USB_ACCESSORY_DETACHED); + intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); + mContext.sendBroadcast(intent); + } + + public void checkPermission(UsbDevice device) { + if (device == null) return; + ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(Binder.getCallingUid()); + if (filterList != null) { + int count = filterList.size(); + for (int i = 0; i < count; i++) { + DeviceFilter filter = filterList.get(i); + if (filter.equals(device)) { + // permission allowed + return; + } + } + } + throw new SecurityException("User has not given permission to device " + device); + } + + public void checkPermission(UsbAccessory accessory) { + if (accessory == null) return; + ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(Binder.getCallingUid()); + if (filterList != null) { + int count = filterList.size(); + for (int i = 0; i < count; i++) { + AccessoryFilter filter = filterList.get(i); + if (filter.equals(accessory)) { + // permission allowed + return; + } + } + } + throw new SecurityException("User has not given permission to accessory " + accessory); + } + + public void setDevicePackage(UsbDevice device, String packageName) { + DeviceFilter filter = new DeviceFilter(device); + if (packageName == null) { + mDevicePreferenceMap.remove(filter); + } else { + mDevicePreferenceMap.put(filter, packageName); + } + // FIXME - only if changed + writeSettings(); + } + + public void setAccessoryPackage(UsbAccessory accessory, String packageName) { + AccessoryFilter filter = new AccessoryFilter(accessory); + if (packageName == null) { + mAccessoryPreferenceMap.remove(filter); + } else { + mAccessoryPreferenceMap.put(filter, packageName); + } + // FIXME - only if changed + writeSettings(); + } + + public void grantDevicePermission(UsbDevice device, int uid) { + ArrayList<DeviceFilter> filterList = mDevicePermissionMap.get(uid); + if (filterList == null) { + filterList = new ArrayList<DeviceFilter>(); + mDevicePermissionMap.put(uid, filterList); + } else { + int count = filterList.size(); + for (int i = 0; i < count; i++) { + if (filterList.get(i).equals(device)) return; + } + } + filterList.add(new DeviceFilter(device)); + writeSettings(); + } + + public void grantAccessoryPermission(UsbAccessory accessory, int uid) { + ArrayList<AccessoryFilter> filterList = mAccessoryPermissionMap.get(uid); + if (filterList == null) { + filterList = new ArrayList<AccessoryFilter>(); + mAccessoryPermissionMap.put(uid, filterList); + } else { + int count = filterList.size(); + for (int i = 0; i < count; i++) { + if (filterList.get(i).equals(accessory)) return; + } + } + filterList.add(new AccessoryFilter(accessory)); + writeSettings(); + } + + public boolean hasDefaults(String packageName, int uid) { + if (mDevicePermissionMap.get(uid) != null) return true; + if (mAccessoryPermissionMap.get(uid) != null) return true; + if (mDevicePreferenceMap.values().contains(packageName)) return true; + if (mAccessoryPreferenceMap.values().contains(packageName)) return true; + return false; + } + + public void clearDefaults(String packageName, int uid) { + boolean packageCleared = clearPackageDefaults(packageName); + boolean uidCleared = clearUidDefaults(uid); + if (packageCleared || uidCleared) { + writeSettings(); + } + } + + private boolean clearUidDefaults(int uid) { + boolean cleared = false; + int index = mDevicePermissionMap.indexOfKey(uid); + if (index >= 0) { + mDevicePermissionMap.removeAt(index); + cleared = true; + } + index = mAccessoryPermissionMap.indexOfKey(uid); + if (index >= 0) { + mAccessoryPermissionMap.removeAt(index); + cleared = true; + } + return cleared; + } + + private boolean clearPackageDefaults(String packageName) { + boolean cleared = false; + if (mDevicePreferenceMap.containsValue(packageName)) { + // make a copy of the key set to avoid ConcurrentModificationException + Object[] keys = mDevicePreferenceMap.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + Object key = keys[i]; + if (packageName.equals(mDevicePreferenceMap.get(key))) { + mDevicePreferenceMap.remove(key); + cleared = true; + } + } + } + if (mAccessoryPreferenceMap.containsValue(packageName)) { + // make a copy of the key set to avoid ConcurrentModificationException + Object[] keys = mAccessoryPreferenceMap.keySet().toArray(); + for (int i = 0; i < keys.length; i++) { + Object key = keys[i]; + if (packageName.equals(mAccessoryPreferenceMap.get(key))) { + mAccessoryPreferenceMap.remove(key); + cleared = true; + } + } + } + return cleared; + } + + public void dump(FileDescriptor fd, PrintWriter pw) { + pw.println(" Device permissions:"); + int count = mDevicePermissionMap.size(); + for (int i = 0; i < count; i++) { + int uid = mDevicePermissionMap.keyAt(i); + pw.println(" " + "uid " + uid + ":"); + ArrayList<DeviceFilter> filters = mDevicePermissionMap.valueAt(i); + for (DeviceFilter filter : filters) { + pw.println(" " + filter); + } + } + pw.println(" Accessory permissions:"); + count = mAccessoryPermissionMap.size(); + for (int i = 0; i < count; i++) { + int uid = mAccessoryPermissionMap.keyAt(i); + pw.println(" " + "uid " + uid + ":"); + ArrayList<AccessoryFilter> filters = mAccessoryPermissionMap.valueAt(i); + for (AccessoryFilter filter : filters) { + pw.println(" " + filter); + } + } + pw.println(" Device preferences:"); + for (DeviceFilter filter : mDevicePreferenceMap.keySet()) { + pw.println(" " + filter + ": " + mDevicePreferenceMap.get(filter)); + } + pw.println(" Accessory preferences:"); + for (AccessoryFilter filter : mAccessoryPreferenceMap.keySet()) { + pw.println(" " + filter + ": " + mAccessoryPreferenceMap.get(filter)); + } + } +} diff --git a/services/java/com/android/server/usb/UsbResolverActivity.java b/services/java/com/android/server/usb/UsbResolverActivity.java new file mode 100644 index 000000000000..1bb3c21bfb6d --- /dev/null +++ b/services/java/com/android/server/usb/UsbResolverActivity.java @@ -0,0 +1,102 @@ +/* + * 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.android.server.usb; + +import com.android.internal.app.ResolverActivity; + +import android.content.ActivityNotFoundException; +import android.content.Intent; +import android.content.pm.ResolveInfo; +import android.hardware.IUsbManager; +import android.hardware.UsbAccessory; +import android.hardware.UsbDevice; +import android.hardware.UsbManager; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcelable; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Log; + +import java.util.ArrayList; + +/* Activity for choosing an application for a USB device or accessory */ +public class UsbResolverActivity extends ResolverActivity { + public static final String TAG = "UsbResolverActivity"; + public static final String EXTRA_RESOLVE_INFOS = "rlist"; + + @Override + protected void onCreate(Bundle savedInstanceState) { + Intent intent = getIntent(); + Parcelable targetParcelable = intent.getParcelableExtra(Intent.EXTRA_INTENT); + if (!(targetParcelable instanceof Intent)) { + Log.w("UsbResolverActivity", "Target is not an intent: " + targetParcelable); + finish(); + return; + } + Intent target = (Intent)targetParcelable; + ArrayList<ResolveInfo> rList = intent.getParcelableArrayListExtra(EXTRA_RESOLVE_INFOS); + Log.d(TAG, "rList.size() " + rList.size()); + CharSequence title = getResources().getText(com.android.internal.R.string.chooseUsbActivity); + super.onCreate(savedInstanceState, target, title, null, rList, + true, /* Set alwaysUseOption to true to enable "always use this app" checkbox. */ + true /* Set alwaysChoose to display activity when only one choice is available. + This is necessary because this activity is needed for the user to allow + the application permission to access the device */ + ); + } + + protected void onIntentSelected(ResolveInfo ri, Intent intent, boolean alwaysCheck) { + try { + IBinder b = ServiceManager.getService(USB_SERVICE); + IUsbManager service = IUsbManager.Stub.asInterface(b); + int uid = ri.activityInfo.applicationInfo.uid; + String action = intent.getAction(); + + if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { + UsbDevice device = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + // grant permission for the device + service.grantDevicePermission(device, uid); + // set or clear default setting + if (alwaysCheck) { + service.setDevicePackage(device, ri.activityInfo.packageName); + } else { + service.setDevicePackage(device, null); + } + } else if (UsbManager.ACTION_USB_ACCESSORY_ATTACHED.equals(action)) { + UsbAccessory accessory = (UsbAccessory)intent.getParcelableExtra( + UsbManager.EXTRA_ACCESSORY); + // grant permission for the accessory + service.grantAccessoryPermission(accessory, uid); + // set or clear default setting + if (alwaysCheck) { + service.setAccessoryPackage(accessory, ri.activityInfo.packageName); + } else { + service.setAccessoryPackage(accessory, null); + } + } + + try { + startActivity(intent); + } catch (ActivityNotFoundException e) { + Log.e(TAG, "startActivity failed", e); + } + } catch (RemoteException e) { + Log.e(TAG, "onIntentSelected failed", e); + } + } +} diff --git a/services/java/com/android/server/UsbService.java b/services/java/com/android/server/usb/UsbService.java index 2f8471352f28..a093d955b34e 100644 --- a/services/java/com/android/server/UsbService.java +++ b/services/java/com/android/server/usb/UsbService.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.android.server; +package com.android.server.usb; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.PackageManager; import android.hardware.IUsbManager; import android.hardware.UsbAccessory; import android.hardware.UsbConstants; @@ -27,6 +28,7 @@ import android.hardware.UsbEndpoint; import android.hardware.UsbInterface; import android.hardware.UsbManager; import android.net.Uri; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -38,10 +40,13 @@ import android.util.Log; import android.util.Slog; import java.io.File; +import java.io.FileDescriptor; import java.io.FileNotFoundException; import java.io.FileReader; +import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; /** * UsbService monitors for changes to USB state. @@ -50,7 +55,7 @@ import java.util.HashMap; * Accessory mode is a special case of USB device mode, where the android device is * connected to a USB host that supports the android accessory protocol. */ -class UsbService extends IUsbManager.Stub { +public class UsbService extends IUsbManager.Stub { private static final String TAG = UsbService.class.getSimpleName(); private static final boolean LOG = false; @@ -102,13 +107,16 @@ class UsbService extends IUsbManager.Stub { private final Context mContext; private final Object mLock = new Object(); + private final UsbDeviceSettingsManager mDeviceManager; + private final boolean mHasUsbHost; + private final boolean mHasUsbAccessory; /* * Handles USB function enable/disable events (device mode) */ private final void functionEnabledLocked(String function, boolean enabled) { boolean enteringAccessoryMode = - (enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function)); + (mHasUsbAccessory && enabled && UsbManager.USB_FUNCTION_ACCESSORY.equals(function)); if (enteringAccessoryMode) { // keep a list of functions to reenable after exiting accessory mode @@ -139,11 +147,9 @@ class UsbService extends IUsbManager.Stub { if (enteringAccessoryMode) { String[] strings = nativeGetAccessoryStrings(); if (strings != null) { - Log.d(TAG, "entering USB accessory mode"); mCurrentAccessory = new UsbAccessory(strings); - Intent intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); - intent.putExtra(UsbManager.EXTRA_ACCESSORY, mCurrentAccessory); - mContext.sendBroadcast(intent); + Log.d(TAG, "entering USB accessory mode: " + mCurrentAccessory); + mDeviceManager.accessoryAttached(mCurrentAccessory); } else { Log.e(TAG, "nativeGetAccessoryStrings failed"); } @@ -170,7 +176,7 @@ class UsbService extends IUsbManager.Stub { mConnected = intState; // trigger an Intent broadcast if (mSystemReady) { - // debounce disconnects + // debounce disconnects to avoid problems bringing up USB tethering update(mConnected == 0); } } else if ("usb_configuration".equals(name)) { @@ -202,6 +208,11 @@ class UsbService extends IUsbManager.Stub { public UsbService(Context context) { mContext = context; + mDeviceManager = new UsbDeviceSettingsManager(context); + PackageManager pm = mContext.getPackageManager(); + mHasUsbHost = pm.hasSystemFeature(PackageManager.FEATURE_USB_HOST); + mHasUsbAccessory = pm.hasSystemFeature(PackageManager.FEATURE_USB_ACCESSORY); + mHostBlacklist = context.getResources().getStringArray( com.android.internal.R.array.config_usbHostBlacklist); @@ -345,11 +356,7 @@ class UsbService extends IUsbManager.Stub { UsbDevice device = new UsbDevice(deviceName, vendorID, productID, deviceClass, deviceSubclass, deviceProtocol, interfaces); mDevices.put(deviceName, device); - - Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); - intent.putExtra(UsbManager.EXTRA_DEVICE, device); - Log.d(TAG, "usbDeviceAdded, sending " + intent); - mContext.sendBroadcast(intent); + mDeviceManager.deviceAttached(device); } } @@ -358,10 +365,7 @@ class UsbService extends IUsbManager.Stub { synchronized (mLock) { UsbDevice device = mDevices.remove(deviceName); if (device != null) { - Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED); - intent.putExtra(UsbManager.EXTRA_DEVICE, device); - Log.d(TAG, "usbDeviceRemoved, sending " + intent); - mContext.sendBroadcast(intent); + mDeviceManager.deviceDetached(device); } } } @@ -377,10 +381,9 @@ class UsbService extends IUsbManager.Stub { new Thread(null, runnable, "UsbService host thread").start(); } - void systemReady() { + public void systemReady() { synchronized (mLock) { - if (mContext.getResources().getBoolean( - com.android.internal.R.bool.config_hasUsbHostSupport)) { + if (mHasUsbHost) { // start monitoring for connected USB devices initHostSupport(); } @@ -402,7 +405,6 @@ class UsbService extends IUsbManager.Stub { /* Returns a list of all currently attached USB devices (host mdoe) */ public void getDeviceList(Bundle devices) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); synchronized (mLock) { for (String name : mDevices.keySet()) { devices.putParcelable(name, mDevices.get(name)); @@ -412,28 +414,85 @@ class UsbService extends IUsbManager.Stub { /* Opens the specified USB device (host mode) */ public ParcelFileDescriptor openDevice(String deviceName) { - if (isBlackListed(deviceName)) { - throw new SecurityException("USB device is on a restricted bus"); - } - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); - if (mDevices.get(deviceName) == null) { - // if it is not in mDevices, it either does not exist or is blacklisted - throw new IllegalArgumentException( - "device " + deviceName + " does not exist or is restricted"); + synchronized (mLock) { + if (isBlackListed(deviceName)) { + throw new SecurityException("USB device is on a restricted bus"); + } + UsbDevice device = mDevices.get(deviceName); + if (device == null) { + // if it is not in mDevices, it either does not exist or is blacklisted + throw new IllegalArgumentException( + "device " + deviceName + " does not exist or is restricted"); + } + mDeviceManager.checkPermission(device); + return nativeOpenDevice(deviceName); } - return nativeOpenDevice(deviceName); } /* returns the currently attached USB accessory (device mode) */ public UsbAccessory getCurrentAccessory() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); - return mCurrentAccessory; + synchronized (mLock) { + mDeviceManager.checkPermission(mCurrentAccessory); + return mCurrentAccessory; + } } /* opens the currently attached USB accessory (device mode) */ - public ParcelFileDescriptor openAccessory() { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null); - return nativeOpenAccessory(); + public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { + synchronized (mLock) { + if (mCurrentAccessory == null) { + throw new IllegalArgumentException("no accessory attached"); + } + if (!mCurrentAccessory.equals(accessory)) { + Log.e(TAG, accessory.toString() + " does not match current accessory " + + mCurrentAccessory); + throw new IllegalArgumentException("accessory not attached"); + } + mDeviceManager.checkPermission(mCurrentAccessory); + return nativeOpenAccessory(); + } + } + + public void setDevicePackage(UsbDevice device, String packageName) { + synchronized (mLock) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.setDevicePackage(device, packageName); + } + } + + public void setAccessoryPackage(UsbAccessory accessory, String packageName) { + synchronized (mLock) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.setAccessoryPackage(accessory, packageName); + } + } + + public void grantDevicePermission(UsbDevice device, int uid) { + synchronized (mLock) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.grantDevicePermission(device, uid); + } + } + + public void grantAccessoryPermission(UsbAccessory accessory, int uid) { + synchronized (mLock) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.grantAccessoryPermission(accessory, uid); + } + } + + public boolean hasDefaults(String packageName, int uid) { + synchronized (mLock) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + return mDeviceManager.hasDefaults(packageName, uid); + } + } + + public void clearDefaults(String packageName, int uid) { + synchronized (mLock) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + mDeviceManager.clearDefaults(packageName, uid); + } } /* @@ -470,10 +529,7 @@ class UsbService extends IUsbManager.Stub { } mAccessoryRestoreFunctions.clear(); - Intent intent = new Intent( - UsbManager.ACTION_USB_ACCESSORY_DETACHED); - intent.putExtra(UsbManager.EXTRA_ACCESSORY, mCurrentAccessory); - mContext.sendBroadcast(intent); + mDeviceManager.accessoryDetached(mCurrentAccessory); mCurrentAccessory = null; // this will cause an immediate reset of the USB bus, @@ -513,6 +569,42 @@ class UsbService extends IUsbManager.Stub { } }; + @Override + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump UsbManager from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + synchronized (mLock) { + pw.println("USB Manager State:"); + + pw.println(" USB Device State:"); + pw.print(" Enabled Functions: "); + for (int i = 0; i < mEnabledFunctions.size(); i++) { + pw.print(mEnabledFunctions.get(i) + " "); + } + pw.println(""); + pw.print(" Disabled Functions: "); + for (int i = 0; i < mDisabledFunctions.size(); i++) { + pw.print(mDisabledFunctions.get(i) + " "); + } + pw.println(""); + pw.println(" mConnected: " + mConnected + ", mConfiguration: " + mConfiguration); + + pw.println(" USB Host State:"); + for (String name : mDevices.keySet()) { + pw.println(" " + name + ": " + mDevices.get(name)); + } + pw.println(" mCurrentAccessory: " + mCurrentAccessory); + + mDeviceManager.dump(fd, pw); + } + } + // host support private native void monitorUsbHostBus(); private native ParcelFileDescriptor nativeOpenDevice(String deviceName); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index b7cc3243255a..e3218c852b17 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -5812,8 +5812,7 @@ public class WindowManagerService extends IWindowManager.Stub mDisplay = wm.getDefaultDisplay(); mInitialDisplayWidth = mDisplay.getWidth(); mInitialDisplayHeight = mDisplay.getHeight(); - mInputManager.setDisplaySize(0, Display.unmapDisplaySize(mInitialDisplayWidth), - Display.unmapDisplaySize(mInitialDisplayHeight)); + mInputManager.setDisplaySize(0, mDisplay.getRealWidth(), mDisplay.getRealHeight()); } try { diff --git a/services/jni/com_android_server_UsbService.cpp b/services/jni/com_android_server_UsbService.cpp index 192daafa1b2d..3c49e546642f 100644 --- a/services/jni/com_android_server_UsbService.cpp +++ b/services/jni/com_android_server_UsbService.cpp @@ -177,7 +177,6 @@ static void set_accessory_string(JNIEnv *env, int fd, int cmd, jobjectArray strA buffer[0] = 0; int length = ioctl(fd, cmd, buffer); - LOGD("ioctl returned %d", length); if (buffer[0]) { jstring obj = env->NewStringUTF(buffer); env->SetObjectArrayElement(strArray, index, obj); @@ -236,9 +235,9 @@ static JNINativeMethod method_table[] = { int register_android_server_UsbService(JNIEnv *env) { - jclass clazz = env->FindClass("com/android/server/UsbService"); + jclass clazz = env->FindClass("com/android/server/usb/UsbService"); if (clazz == NULL) { - LOGE("Can't find com/android/server/UsbService"); + LOGE("Can't find com/android/server/usb/UsbService"); return -1; } method_usbDeviceAdded = env->GetMethodID(clazz, "usbDeviceAdded", "(Ljava/lang/String;IIIII[I[I)V"); @@ -267,7 +266,7 @@ int register_android_server_UsbService(JNIEnv *env) LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL, "Unable to find constructor for android.os.ParcelFileDescriptor"); - return jniRegisterNativeMethods(env, "com/android/server/UsbService", + return jniRegisterNativeMethods(env, "com/android/server/usb/UsbService", method_table, NELEM(method_table)); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index fd3f0c263072..40882d8f9309 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2470,7 +2470,7 @@ ssize_t UserClient::getTokenForSurface(const sp<ISurface>& sur) const } break; } - if (++name > 31) + if (++name >= SharedBufferStack::NUM_LAYERS_MAX) name = NO_MEMORY; } while(name >= 0); diff --git a/telephony/java/com/android/internal/telephony/IWapPushManager.aidl b/telephony/java/com/android/internal/telephony/IWapPushManager.aidl new file mode 100644 index 000000000000..d5ecb940c8d1 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/IWapPushManager.aidl @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +import android.content.Intent; + +interface IWapPushManager { + /** + * Processes WAP push message and triggers the receiver application registered + * in the application ID table. + */ + int processMessage(String app_id, String content_type, in Intent intent); + + /** + * Add receiver application into the application ID table. + * Returns true if inserting the information is successfull. Inserting the duplicated + * record in the application ID table is not allowed. Use update/delete method. + */ + boolean addPackage(String x_app_id, String content_type, + String package_name, String class_name, + int app_type, boolean need_signature, boolean further_processing); + + /** + * Updates receiver application that is last added. + * Returns true if updating the information is successfull. + */ + boolean updatePackage(String x_app_id, String content_type, + String package_name, String class_name, + int app_type, boolean need_signature, boolean further_processing); + + /** + * Delites receiver application information. + * Returns true if deleting is successfull. + */ + boolean deletePackage(String x_app_id, String content_type, + String package_name, String class_name); +} + diff --git a/telephony/java/com/android/internal/telephony/WapPushManagerParams.java b/telephony/java/com/android/internal/telephony/WapPushManagerParams.java new file mode 100644 index 000000000000..11e5ff9e0858 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/WapPushManagerParams.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony; + +/** + * WapPushManager constant value definitions + */ +public class WapPushManagerParams { + /** + * Application type activity + */ + public static final int APP_TYPE_ACTIVITY = 0; + + /** + * Application type service + */ + public static final int APP_TYPE_SERVICE = 1; + + /** + * Process Message return value + * Message is handled + */ + public static final int MESSAGE_HANDLED = 0x1; + + /** + * Process Message return value + * Application ID or content type was not found in the application ID table + */ + public static final int APP_QUERY_FAILED = 0x2; + + /** + * Process Message return value + * Receiver application signature check failed + */ + public static final int SIGNATURE_NO_MATCH = 0x4; + + /** + * Process Message return value + * Receiver application was not found + */ + public static final int INVALID_RECEIVER_NAME = 0x8; + + /** + * Process Message return value + * Unknown exception + */ + public static final int EXCEPTION_CAUGHT = 0x10; + + /** + * Process Message return value + * Need further processing after WapPushManager message processing + */ + public static final int FURTHER_PROCESSING = 0x8000; + +} + diff --git a/telephony/java/com/android/internal/telephony/WapPushOverSms.java b/telephony/java/com/android/internal/telephony/WapPushOverSms.java index 2f5d3eccf95c..77046677667c 100644 --- a/telephony/java/com/android/internal/telephony/WapPushOverSms.java +++ b/telephony/java/com/android/internal/telephony/WapPushOverSms.java @@ -14,15 +14,20 @@ * limitations under the License. */ + package com.android.internal.telephony; import android.app.Activity; import android.content.Context; +import android.content.ComponentName; import android.content.Intent; +import android.content.ServiceConnection; import android.provider.Telephony; import android.provider.Telephony.Sms.Intents; import android.util.Config; import android.util.Log; +import android.os.IBinder; +import android.os.RemoteException; /** * WAP push handler class. @@ -42,11 +47,83 @@ public class WapPushOverSms { */ private final int WAKE_LOCK_TIMEOUT = 5000; + private final int BIND_RETRY_INTERVAL = 1000; + /** + * A handle to WapPushManager interface + */ + private WapPushConnection mWapConn = null; + private class WapPushConnection implements ServiceConnection { + private IWapPushManager mWapPushMan; + private Context mOwner; + + public WapPushConnection(Context ownerContext) { + mOwner = ownerContext; + } + + public void onServiceConnected(ComponentName name, IBinder service) { + mWapPushMan = IWapPushManager.Stub.asInterface(service); + if (Config.DEBUG) Log.v(LOG_TAG, "wappush manager connected to " + + mOwner.hashCode()); + } + + public void onServiceDisconnected(ComponentName name) { + mWapPushMan = null; + if (Config.DEBUG) Log.v(LOG_TAG, "wappush manager disconnected."); + // WapPushManager must be always attached. + rebindWapPushManager(); + } + + /** + * bind WapPushManager + */ + public void bindWapPushManager() { + if (mWapPushMan != null) return; + + final ServiceConnection wapPushConnection = this; + + mOwner.bindService(new Intent(IWapPushManager.class.getName()), + wapPushConnection, Context.BIND_AUTO_CREATE); + } + + /** + * rebind WapPushManager + * This method is called when WapPushManager is disconnected unexpectedly. + */ + private void rebindWapPushManager() { + if (mWapPushMan != null) return; + + final ServiceConnection wapPushConnection = this; + new Thread() { + public void run() { + while (mWapPushMan == null) { + mOwner.bindService(new Intent(IWapPushManager.class.getName()), + wapPushConnection, Context.BIND_AUTO_CREATE); + try { + Thread.sleep(BIND_RETRY_INTERVAL); + } catch (InterruptedException e) { + if (Config.DEBUG) Log.v(LOG_TAG, "sleep interrupted."); + } + } + } + }.start(); + } + + /** + * Returns interface to WapPushManager + */ + public IWapPushManager getWapPushManager() { + return mWapPushMan; + } + } + public WapPushOverSms(Phone phone, SMSDispatcher smsDispatcher) { mSmsDispatcher = smsDispatcher; mContext = phone.getContext(); + mWapConn = new WapPushConnection(mContext); + mWapConn.bindWapPushManager(); } + /** * Dispatches inbound messages that are in the WAP PDU format. See * wap-230-wsp-20010705-a section 8 for details on the WAP PDU format. @@ -106,16 +183,15 @@ public class WapPushOverSms { } String mimeType = pduDecoder.getValueString(); - + long binaryContentType = pduDecoder.getValue32(); index += pduDecoder.getDecodedDataLength(); byte[] header = new byte[headerLength]; System.arraycopy(pdu, headerStartIndex, header, 0, header.length); byte[] intentData; - String permission; - if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { + if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) { intentData = pdu; } else { int dataIndex = headerStartIndex + headerLength; @@ -123,6 +199,62 @@ public class WapPushOverSms { System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length); } + /** + * Seek for application ID field in WSP header. + * If application ID is found, WapPushManager substitute the message + * processing. Since WapPushManager is optional module, if WapPushManager + * is not found, legacy message processing will be continued. + */ + if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) { + index = (int) pduDecoder.getValue32(); + pduDecoder.decodeXWapApplicationId(index); + String wapAppId = pduDecoder.getValueString(); + if (wapAppId == null) { + wapAppId = Integer.toString((int) pduDecoder.getValue32()); + } + + String contentType = ((mimeType == null) ? + Long.toString(binaryContentType) : mimeType); + if (Config.DEBUG) Log.v(LOG_TAG, "appid found: " + wapAppId + ":" + contentType); + + try { + boolean processFurther = true; + IWapPushManager wapPushMan = mWapConn.getWapPushManager(); + + if (wapPushMan == null) { + if (Config.DEBUG) Log.w(LOG_TAG, "wap push manager not found!"); + } else { + Intent intent = new Intent(); + intent.putExtra("transactionId", transactionId); + intent.putExtra("pduType", pduType); + intent.putExtra("header", header); + intent.putExtra("data", intentData); + intent.putExtra("contentTypeParameters", + pduDecoder.getContentParameters()); + + int procRet = wapPushMan.processMessage(wapAppId, contentType, intent); + if (Config.DEBUG) Log.v(LOG_TAG, "procRet:" + procRet); + if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0 + && (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) { + processFurther = false; + } + } + if (!processFurther) { + return Intents.RESULT_SMS_HANDLED; + } + } catch (RemoteException e) { + if (Config.DEBUG) Log.w(LOG_TAG, "remote func failed..."); + } + } + if (Config.DEBUG) Log.v(LOG_TAG, "fall back to existing handler"); + + if (mimeType == null) { + if (Config.DEBUG) Log.w(LOG_TAG, "Header Content-Type error."); + return Intents.RESULT_SMS_GENERIC_ERROR; + } + + String permission; + if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_MMS)) { permission = "android.permission.RECEIVE_MMS"; } else { @@ -141,4 +273,4 @@ public class WapPushOverSms { return Activity.RESULT_OK; } -}
\ No newline at end of file +} diff --git a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java index 6bf6b1315e5a..c8dd7181aef9 100644 --- a/telephony/java/com/android/internal/telephony/WspTypeDecoder.java +++ b/telephony/java/com/android/internal/telephony/WspTypeDecoder.java @@ -37,6 +37,7 @@ public class WspTypeDecoder { private final static HashMap<Integer, String> WELL_KNOWN_PARAMETERS = new HashMap<Integer, String>(); + public static final int PARAMETER_ID_X_WAP_APPLICATION_ID = 0x2f; private static final int Q_VALUE = 0x00; static { @@ -603,6 +604,70 @@ public class WspTypeDecoder { } /** + * Seek for the "X-Wap-Application-Id" field for WSP pdu + * + * @param startIndex The starting position of seek pointer + * @param endIndex Valid seek area end point + * + * @return false when error(not a X-Wap-Application-Id) occur + * return value can be retrieved by getValue32() + */ + public boolean seekXWapApplicationId(int startIndex, int endIndex) { + int index = startIndex; + + try { + for (index = startIndex; index <= endIndex; ) { + /** + * 8.4.1.1 Field name + * Field name is integer or text. + */ + if (decodeIntegerValue(index)) { + int fieldValue = (int) getValue32(); + + if (fieldValue == PARAMETER_ID_X_WAP_APPLICATION_ID) { + unsigned32bit = index + 1; + return true; + } + } else { + if (!decodeTextString(index)) return false; + } + index += getDecodedDataLength(); + if (index > endIndex) return false; + + /** + * 8.4.1.2 Field values + * Value Interpretation of First Octet + * 0 - 30 This octet is followed by the indicated number (0 - 30) + of data octets + * 31 This octet is followed by a uintvar, which indicates the number + * of data octets after it + * 32 - 127 The value is a text string, terminated by a zero octet + (NUL character) + * 128 - 255 It is an encoded 7-bit value; this header has no more data + */ + byte val = wspData[index]; + if (0 <= val && val <= WAP_PDU_SHORT_LENGTH_MAX) { + index += wspData[index] + 1; + } else if (val == WAP_PDU_LENGTH_QUOTE) { + if (index + 1 >= endIndex) return false; + index++; + if (!decodeUintvarInteger(index)) return false; + index += getDecodedDataLength(); + } else if (WAP_PDU_LENGTH_QUOTE < val && val <= 127) { + if (!decodeTextString(index)) return false; + index += getDecodedDataLength(); + } else { + index++; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + //seek application ID failed. WSP header might be corrupted + return false; + } + return false; + } + + /** * Decode the "X-Wap-Content-URI" type for WSP pdu * * @param startIndex The starting position of the "X-Wap-Content-URI" in this pdu diff --git a/test-runner/src/android/test/SingleLaunchActivityTestCase.java b/test-runner/src/android/test/SingleLaunchActivityTestCase.java index b63b3ce19759..79c554a46391 100644 --- a/test-runner/src/android/test/SingleLaunchActivityTestCase.java +++ b/test-runner/src/android/test/SingleLaunchActivityTestCase.java @@ -75,7 +75,7 @@ public abstract class SingleLaunchActivityTestCase<T extends Activity> protected void tearDown() throws Exception { // If it is the last test case, call finish on the activity. sTestCaseCounter --; - if (sTestCaseCounter == 1) { + if (sTestCaseCounter == 0) { sActivity.finish(); } super.tearDown(); diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h index c5aa5732bb0e..15570e47e6a1 100644 --- a/tools/aapt/Bundle.h +++ b/tools/aapt/Bundle.h @@ -45,7 +45,7 @@ public: mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL), mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL), mVersionCode(NULL), mVersionName(NULL), mCustomPackage(NULL), - mMaxResVersion(NULL), mDebugMode(false), mProduct(NULL), + mMaxResVersion(NULL), mDebugMode(false), mNonConstantId(false), mProduct(NULL), mArgc(0), mArgv(NULL) {} ~Bundle(void) {} @@ -139,6 +139,8 @@ public: void setMaxResVersion(const char * val) { mMaxResVersion = val; } bool getDebugMode() { return mDebugMode; } void setDebugMode(bool val) { mDebugMode = val; } + bool getNonConstantId() { return mNonConstantId; } + void setNonConstantId(bool val) { mNonConstantId = val; } const char* getProduct() const { return mProduct; } void setProduct(const char * val) { mProduct = val; } @@ -239,6 +241,7 @@ private: const char* mCustomPackage; const char* mMaxResVersion; bool mDebugMode; + bool mNonConstantId; const char* mProduct; /* file specification */ diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp index 739b01f40d24..266a02f25a17 100644 --- a/tools/aapt/Main.cpp +++ b/tools/aapt/Main.cpp @@ -160,7 +160,11 @@ void usage(void) " product variants\n" " --utf16\n" " changes default encoding for resources to UTF-16. Only useful when API\n" - " level is set to 7 or higher where the default encoding is UTF-8.\n"); + " level is set to 7 or higher where the default encoding is UTF-8.\n" + " --non-constant-id\n" + " Make the resources ID non constant. This is required to make an R java class\n" + " that does not contain the final value but is used to make reusable compiled\n" + " libraries that need to access resources.\n"); } /* @@ -497,6 +501,8 @@ int main(int argc, char* const argv[]) goto bail; } bundle.setProduct(argv[0]); + } else if (strcmp(cp, "-non-constant-id") == 0) { + bundle.setNonConstantId(true); } else { fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp); wantUsage = true; diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 7f84df60e66f..730bd71160f8 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -1723,7 +1723,8 @@ static status_t writeLayoutClasses( static status_t writeSymbolClass( FILE* fp, const sp<AaptAssets>& assets, bool includePrivate, - const sp<AaptSymbols>& symbols, const String8& className, int indent) + const sp<AaptSymbols>& symbols, const String8& className, int indent, + bool nonConstantId) { fprintf(fp, "%spublic %sfinal class %s {\n", getIndentSpace(indent), @@ -1733,6 +1734,10 @@ static status_t writeSymbolClass( size_t i; status_t err = NO_ERROR; + const char * id_format = nonConstantId ? + "%spublic static int %s=0x%08x;\n" : + "%spublic static final int %s=0x%08x;\n"; + size_t N = symbols->getSymbols().size(); for (i=0; i<N; i++) { const AaptSymbolEntry& sym = symbols->getSymbols().valueAt(i); @@ -1785,7 +1790,7 @@ static status_t writeSymbolClass( if (deprecated) { fprintf(fp, "%s@Deprecated\n", getIndentSpace(indent)); } - fprintf(fp, "%spublic static final int %s=0x%08x;\n", + fprintf(fp, id_format, getIndentSpace(indent), String8(name).string(), (int)sym.int32Val); } @@ -1836,7 +1841,7 @@ static status_t writeSymbolClass( if (nclassName == "styleable") { styleableSymbols = nsymbols; } else { - err = writeSymbolClass(fp, assets, includePrivate, nsymbols, nclassName, indent); + err = writeSymbolClass(fp, assets, includePrivate, nsymbols, nclassName, indent, nonConstantId); } if (err != NO_ERROR) { return err; @@ -1907,7 +1912,7 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, "\n" "package %s;\n\n", package.string()); - status_t err = writeSymbolClass(fp, assets, includePrivate, symbols, className, 0); + status_t err = writeSymbolClass(fp, assets, includePrivate, symbols, className, 0, bundle->getNonConstantId()); if (err != NO_ERROR) { return err; } |