diff options
23 files changed, 475 insertions, 119 deletions
diff --git a/api/current.txt b/api/current.txt index 520d05aae66e..b734c677fee0 100644 --- a/api/current.txt +++ b/api/current.txt @@ -3161,6 +3161,14 @@ package android.app { method public void update(android.app.ActivityOptions); } + public class ActivityView extends android.view.ViewGroup { + ctor public ActivityView(android.content.Context); + ctor public ActivityView(android.content.Context, android.util.AttributeSet); + ctor public ActivityView(android.content.Context, android.util.AttributeSet, int); + method protected void onLayout(boolean, int, int, int, int); + method public void startActivity(android.content.Intent); + } + public class AlarmManager { method public void cancel(android.app.PendingIntent); method public void set(int, long, android.app.PendingIntent); diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 3bc2ee60c10a..7b81713c0fcc 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2027,7 +2027,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM IActivityContainer activityContainer = createActivityContainer(parentActivityToken, callback); reply.writeNoException(); - reply.writeStrongBinder(activityContainer.asBinder()); + if (activityContainer != null) { + reply.writeInt(1); + reply.writeStrongBinder(activityContainer.asBinder()); + } else { + reply.writeInt(0); + } return true; } @@ -2036,7 +2041,12 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM IBinder activityToken = data.readStrongBinder(); IActivityContainer activityContainer = getEnclosingActivityContainer(activityToken); reply.writeNoException(); - reply.writeStrongBinder(activityContainer.asBinder()); + if (activityContainer != null) { + reply.writeInt(1); + reply.writeStrongBinder(activityContainer.asBinder()); + } else { + reply.writeInt(0); + } return true; } @@ -4670,8 +4680,13 @@ class ActivityManagerProxy implements IActivityManager data.writeStrongBinder((IBinder)callback); mRemote.transact(CREATE_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0); reply.readException(); - IActivityContainer res = - IActivityContainer.Stub.asInterface(reply.readStrongBinder()); + final int result = reply.readInt(); + final IActivityContainer res; + if (result == 1) { + res = IActivityContainer.Stub.asInterface(reply.readStrongBinder()); + } else { + res = null; + } data.recycle(); reply.recycle(); return res; @@ -4685,8 +4700,13 @@ class ActivityManagerProxy implements IActivityManager data.writeStrongBinder(activityToken); mRemote.transact(GET_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0); reply.readException(); - IActivityContainer res = - IActivityContainer.Stub.asInterface(reply.readStrongBinder()); + final int result = reply.readInt(); + final IActivityContainer res; + if (result == 1) { + res = IActivityContainer.Stub.asInterface(reply.readStrongBinder()); + } else { + res = null; + } data.recycle(); reply.recycle(); return res; diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 94ebff97d496..5239cc6d3af4 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -2235,7 +2235,8 @@ public final class ActivityThread { try { IActivityContainer container = ActivityManagerNative.getDefault().getEnclosingActivityContainer(r.token); - final int displayId = container.getDisplayId(); + final int displayId = + container == null ? Display.DEFAULT_DISPLAY : container.getDisplayId(); if (displayId > Display.DEFAULT_DISPLAY) { Display display = dm.getRealDisplay(displayId, r.token); baseContext = appContext.createDisplayContext(display); diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java new file mode 100644 index 000000000000..fef4597e4e4e --- /dev/null +++ b/core/java/android/app/ActivityView.java @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import android.content.Context; +import android.content.ContextWrapper; +import android.content.Intent; +import android.graphics.SurfaceTexture; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.Surface; +import android.view.TextureView; +import android.view.TextureView.SurfaceTextureListener; +import android.view.ViewGroup; +import android.view.WindowManager; + +public class ActivityView extends ViewGroup { + private final TextureView mTextureView; + private IActivityContainer mActivityContainer; + private Activity mActivity; + private boolean mAttached; + private int mWidth; + private int mHeight; + + public ActivityView(Context context) { + this(context, null); + } + + public ActivityView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ActivityView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + while (context instanceof ContextWrapper) { + if (context instanceof Activity) { + mActivity = (Activity)context; + break; + } + context = ((ContextWrapper)context).getBaseContext(); + } + if (mActivity == null) { + throw new IllegalStateException("The ActivityView's Context is not an Activity."); + } + + mTextureView = new TextureView(context); + mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener()); + addView(mTextureView); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + mTextureView.layout(l, t, r, b); + } + + @Override + protected void onAttachedToWindow() { + try { + final IBinder token = mActivity.getActivityToken(); + mActivityContainer = + ActivityManagerNative.getDefault().createActivityContainer(token, null); + } catch (RemoteException e) { + throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. " + + e); + } + + final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture(); + if (surfaceTexture != null) { + createActivityView(surfaceTexture); + } + } + + @Override + protected void onDetachedFromWindow() { + if (mActivityContainer != null) { + try { + mActivityContainer.deleteActivityView(); + } catch (RemoteException e) { + } + mActivityContainer = null; + } + mAttached = false; + } + + public void startActivity(Intent intent) { + if (mActivityContainer != null && mAttached) { + try { + mActivityContainer.startActivity(intent); + } catch (RemoteException e) { + throw new IllegalStateException("ActivityView: Unable to startActivity. " + e); + } + } + } + + /** Call when both mActivityContainer and mTextureView's SurfaceTexture are not null */ + private void createActivityView(SurfaceTexture surfaceTexture) { + WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE); + DisplayMetrics metrics = new DisplayMetrics(); + wm.getDefaultDisplay().getMetrics(metrics); + + try { + mActivityContainer.createActivityView(new Surface(surfaceTexture), mWidth, mHeight, + metrics.densityDpi); + } catch (RemoteException e) { + mActivityContainer = null; + throw new IllegalStateException( + "ActivityView: Unable to create ActivityContainer. " + e); + } + mAttached = true; + } + + private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener { + @Override + public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, + int height) { + mWidth = width; + mHeight = height; + if (mActivityContainer != null) { + createActivityView(surfaceTexture); + } + } + + @Override + public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, + int height) { + } + + @Override + public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { + try { + mActivityContainer.deleteActivityView(); + // TODO: Add binderDied to handle this nullification. + mActivityContainer = null; + } catch (RemoteException r) { + } + mAttached = false; + return false; + } + + @Override + public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { + + } + + } +} diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl index 2d8d18f0c328..b03a459a95a4 100644 --- a/core/java/android/app/IActivityContainer.aidl +++ b/core/java/android/app/IActivityContainer.aidl @@ -19,6 +19,7 @@ package android.app; import android.app.IActivityContainerCallback; import android.content.Intent; import android.os.IBinder; +import android.view.Surface; /** @hide */ interface IActivityContainer { @@ -26,4 +27,6 @@ interface IActivityContainer { int getDisplayId(); void detachFromDisplay(); int startActivity(in Intent intent); + void createActivityView(in Surface surface, int width, int height, int density); + void deleteActivityView(); } diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java index bcf0b637a213..39286d6ea9b6 100644 --- a/core/java/android/content/ContentProviderNative.java +++ b/core/java/android/content/ContentProviderNative.java @@ -112,17 +112,24 @@ abstract public class ContentProviderNative extends Binder implements IContentPr Cursor cursor = query(callingPkg, url, projection, selection, selectionArgs, sortOrder, cancellationSignal); if (cursor != null) { + CursorToBulkCursorAdaptor adaptor = null; + try { - CursorToBulkCursorAdaptor adaptor = new CursorToBulkCursorAdaptor( - cursor, observer, getProviderName()); - BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor(); + adaptor = new CursorToBulkCursorAdaptor(cursor, observer, + getProviderName()); cursor = null; + BulkCursorDescriptor d = adaptor.getBulkCursorDescriptor(); + adaptor = null; + reply.writeNoException(); reply.writeInt(1); d.writeToParcel(reply, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } finally { // Close cursor if an exception was thrown while constructing the adaptor. + if (adaptor != null) { + adaptor.close(); + } if (cursor != null) { cursor.close(); } diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 94b961793e26..b13262752bfa 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -29,6 +29,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.io.ObjectStreamClass; import java.io.Serializable; import java.lang.reflect.Field; import java.util.ArrayList; @@ -2061,7 +2062,7 @@ public final class Parcel { return readByte(); case VAL_SERIALIZABLE: - return readSerializable(); + return readSerializable(loader); case VAL_PARCELABLEARRAY: return readParcelableArray(loader); @@ -2198,6 +2199,10 @@ public final class Parcel { * wasn't found in the parcel. */ public final Serializable readSerializable() { + return readSerializable(null); + } + + private final Serializable readSerializable(final ClassLoader loader) { String name = readString(); if (name == null) { // For some reason we were unable to read the name of the Serializable (either there @@ -2209,14 +2214,27 @@ public final class Parcel { byte[] serializedData = createByteArray(); ByteArrayInputStream bais = new ByteArrayInputStream(serializedData); try { - ObjectInputStream ois = new ObjectInputStream(bais); + ObjectInputStream ois = new ObjectInputStream(bais) { + @Override + protected Class<?> resolveClass(ObjectStreamClass osClass) + throws IOException, ClassNotFoundException { + // try the custom classloader if provided + if (loader != null) { + Class<?> c = Class.forName(osClass.getName(), false, loader); + if (c != null) { + return c; + } + } + return super.resolveClass(osClass); + } + }; return (Serializable) ois.readObject(); } catch (IOException ioe) { throw new RuntimeException("Parcelable encountered " + "IOException reading a Serializable object (name = " + name + ")", ioe); } catch (ClassNotFoundException cnfe) { - throw new RuntimeException("Parcelable encountered" + + throw new RuntimeException("Parcelable encountered " + "ClassNotFoundException reading a Serializable object (name = " + name + ")", cnfe); } diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java index 0d14a9e29f69..04180491f137 100644 --- a/core/java/android/preference/PreferenceActivity.java +++ b/core/java/android/preference/PreferenceActivity.java @@ -33,7 +33,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; import android.util.AttributeSet; -import android.util.Log; import android.util.TypedValue; import android.util.Xml; import android.view.LayoutInflater; @@ -1173,7 +1172,7 @@ public abstract class PreferenceActivity extends ListActivity implements } } - private void switchToHeaderInner(String fragmentName, Bundle args, int direction) { + private void switchToHeaderInner(String fragmentName, Bundle args) { getFragmentManager().popBackStack(BACK_STACK_PREFS, FragmentManager.POP_BACK_STACK_INCLUSIVE); if (!isValidFragment(fragmentName)) { @@ -1196,7 +1195,7 @@ public abstract class PreferenceActivity extends ListActivity implements */ public void switchToHeader(String fragmentName, Bundle args) { setSelectedHeader(null); - switchToHeaderInner(fragmentName, args, 0); + switchToHeaderInner(fragmentName, args); } /** @@ -1215,8 +1214,7 @@ public abstract class PreferenceActivity extends ListActivity implements if (header.fragment == null) { throw new IllegalStateException("can't switch to header that has no fragment"); } - int direction = mHeaders.indexOf(header) - mHeaders.indexOf(mCurHeader); - switchToHeaderInner(header.fragment, header.fragmentArguments, direction); + switchToHeaderInner(header.fragment, header.fragmentArguments); setSelectedHeader(header); } } diff --git a/core/java/android/widget/ActionMenuPresenter.java b/core/java/android/widget/ActionMenuPresenter.java index b75d12fbacab..01abf2ceb09b 100644 --- a/core/java/android/widget/ActionMenuPresenter.java +++ b/core/java/android/widget/ActionMenuPresenter.java @@ -168,8 +168,24 @@ public class ActionMenuPresenter extends BaseMenuPresenter } actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE); + final ActionMenuView menuParent = (ActionMenuView) parent; + final ViewGroup.LayoutParams lp = actionView.getLayoutParams(); + if (!menuParent.checkLayoutParams(lp)) { + actionView.setLayoutParams(menuParent.generateLayoutParams(lp)); + } + return actionView; + } + + @Override + public void bindItemView(final MenuItemImpl item, MenuView.ItemView itemView) { + itemView.initialize(item, 0); + + final ActionMenuView menuView = (ActionMenuView) mMenuView; + final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; + actionItemView.setItemInvoker(menuView); + if (item.hasSubMenu()) { - actionView.setOnTouchListener(new ForwardingListener(actionView) { + actionItemView.setOnTouchListener(new ForwardingListener(actionItemView) { @Override public ListPopupWindow getPopup() { return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null; @@ -186,24 +202,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter } }); } else { - actionView.setOnTouchListener(null); + actionItemView.setOnTouchListener(null); } - - final ActionMenuView menuParent = (ActionMenuView) parent; - final ViewGroup.LayoutParams lp = actionView.getLayoutParams(); - if (!menuParent.checkLayoutParams(lp)) { - actionView.setLayoutParams(menuParent.generateLayoutParams(lp)); - } - return actionView; - } - - @Override - public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) { - itemView.initialize(item, 0); - - final ActionMenuView menuView = (ActionMenuView) mMenuView; - ActionMenuItemView actionItemView = (ActionMenuItemView) itemView; - actionItemView.setItemInvoker(menuView); } @Override diff --git a/data/keyboards/AVRCP.kl b/data/keyboards/AVRCP.kl index 4c91ece3b5ef..736b43c80c4d 100644 --- a/data/keyboards/AVRCP.kl +++ b/data/keyboards/AVRCP.kl @@ -14,8 +14,8 @@ # Key layout used for Bluetooth AVRCP support. -key 200 MEDIA_PLAY_PAUSE WAKE -key 201 MEDIA_PLAY_PAUSE WAKE +key 200 MEDIA_PLAY WAKE +key 201 MEDIA_PAUSE WAKE key 166 MEDIA_STOP WAKE key 163 MEDIA_NEXT WAKE key 165 MEDIA_PREVIOUS WAKE diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index a1e0772856ce..a98b84f20c61 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -50,6 +50,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { private Drawable mCurrDrawable; private int mAlpha = 0xFF; + /** Whether setAlpha() has been called at least once. */ + private boolean mHasAlpha; + private int mCurIndex = -1; private boolean mMutated; @@ -117,6 +120,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public void setAlpha(int alpha) { + mHasAlpha = true; + if (mAlpha != alpha) { mAlpha = alpha; if (mCurrDrawable != null) { @@ -146,8 +151,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public void setColorFilter(ColorFilter cf) { + mDrawableContainerState.mHasColorFilter = true; + if (mDrawableContainerState.mColorFilter != cf) { mDrawableContainerState.mColorFilter = cf; + if (mCurrDrawable != null) { mCurrDrawable.mutate().setColorFilter(cf); } @@ -189,9 +197,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public void setAutoMirrored(boolean mirrored) { - mDrawableContainerState.mAutoMirrored = mirrored; - if (mCurrDrawable != null) { - mCurrDrawable.mutate().setAutoMirrored(mDrawableContainerState.mAutoMirrored); + if (mDrawableContainerState.mAutoMirrored != mirrored) { + mDrawableContainerState.mAutoMirrored = mirrored; + if (mCurrDrawable != null) { + mCurrDrawable.mutate().setAutoMirrored(mDrawableContainerState.mAutoMirrored); + } } } @@ -210,7 +220,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } if (mCurrDrawable != null) { mCurrDrawable.jumpToCurrentState(); - mCurrDrawable.mutate().setAlpha(mAlpha); + if (mHasAlpha) { + mCurrDrawable.mutate().setAlpha(mAlpha); + } } if (mExitAnimationEnd != 0) { mExitAnimationEnd = 0; @@ -353,12 +365,14 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { d.mutate(); if (mDrawableContainerState.mEnterFadeDuration > 0) { mEnterAnimationEnd = now + mDrawableContainerState.mEnterFadeDuration; - } else { + } else if (mHasAlpha) { d.setAlpha(mAlpha); } + if (mDrawableContainerState.mHasColorFilter) { + d.setColorFilter(mDrawableContainerState.mColorFilter); + } d.setVisible(isVisible(), true); d.setDither(mDrawableContainerState.mDither); - d.setColorFilter(mDrawableContainerState.mColorFilter); d.setState(getState()); d.setLevel(getLevel()); d.setBounds(getBounds()); @@ -394,6 +408,8 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { } void animate(boolean schedule) { + mHasAlpha = true; + final long now = SystemClock.uptimeMillis(); boolean animating = false; if (mCurrDrawable != null) { @@ -507,6 +523,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mAutoMirrored; ColorFilter mColorFilter; + boolean mHasColorFilter; DrawableContainerState(DrawableContainerState orig, DrawableContainer owner, Resources res) { @@ -529,6 +546,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { mExitFadeDuration = orig.mExitFadeDuration; mAutoMirrored = orig.mAutoMirrored; mColorFilter = orig.mColorFilter; + mHasColorFilter = orig.mHasColorFilter; // Cloning the following values may require creating futures. mConstantPadding = orig.getConstantPadding(); diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index f2e9988f4c0c..51c183f582be 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -342,6 +342,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { childDrawable.mInsetT = t; childDrawable.mInsetR = r; childDrawable.mInsetB = b; + invalidatePadding(); } /** diff --git a/media/jni/Android.mk b/media/jni/Android.mk index 685bbcc784af..a45051c93df3 100644 --- a/media/jni/Android.mk +++ b/media/jni/Android.mk @@ -37,17 +37,14 @@ LOCAL_SHARED_LIBRARIES := \ libcamera_client \ libmtp \ libusbhost \ - libjhead \ + libexif \ libstagefright_amrnb_common \ -LOCAL_REQUIRED_MODULES := \ - libjhead_jni - LOCAL_STATIC_LIBRARIES := \ libstagefright_amrnbenc LOCAL_C_INCLUDES += \ - external/jhead \ + external/libexif/ \ external/tremor/Tremor \ frameworks/base/core/jni \ frameworks/av/media/libmedia \ diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp index 72ce3cce0325..4fbc55a3fa87 100644 --- a/media/jni/android_mtp_MtpDatabase.cpp +++ b/media/jni/android_mtp_MtpDatabase.cpp @@ -37,7 +37,10 @@ #include "mtp.h" extern "C" { -#include "jhead.h" +#include "libexif/exif-content.h" +#include "libexif/exif-data.h" +#include "libexif/exif-tag.h" +#include "libexif/exif-utils.h" } using namespace android; @@ -750,6 +753,22 @@ MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle, return result; } +static void foreachentry(ExifEntry *entry, void *user) { + char buf[1024]; + ALOGI("entry %x, format %d, size %d: %s", + entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf))); +} + +static void foreachcontent(ExifContent *content, void *user) { + ALOGI("content %d", exif_content_get_ifd(content)); + exif_content_foreach_entry(content, foreachentry, user); +} + +static long getLongFromExifEntry(ExifEntry *e) { + ExifByteOrder o = exif_data_get_byte_order(e->parent->parent); + return exif_get_long(e->data, o); +} + MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, MtpObjectInfo& info) { char date[20]; @@ -792,23 +811,22 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, // read EXIF data for thumbnail information if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) { - ResetJpgfile(); - // Start with an empty image information structure. - memset(&ImageInfo, 0, sizeof(ImageInfo)); - ImageInfo.FlashUsed = -1; - ImageInfo.MeteringMode = -1; - ImageInfo.Whitebalance = -1; - strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX); - if (ReadJpegFile((const char*)path, READ_METADATA)) { - Section_t* section = FindSection(M_EXIF); - if (section) { - info.mThumbCompressedSize = ImageInfo.ThumbnailSize; - info.mThumbFormat = MTP_FORMAT_EXIF_JPEG; - info.mImagePixWidth = ImageInfo.Width; - info.mImagePixHeight = ImageInfo.Height; - } + + ExifData *exifdata = exif_data_new_from_file(path); + if (exifdata) { + //exif_data_foreach_content(exifdata, foreachcontent, NULL); + + // XXX get this from exif, or parse jpeg header instead? + ExifEntry *w = exif_content_get_entry( + exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION); + ExifEntry *h = exif_content_get_entry( + exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION); + info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0; + info.mThumbFormat = MTP_FORMAT_EXIF_JPEG; + info.mImagePixWidth = getLongFromExifEntry(w); + info.mImagePixHeight = getLongFromExifEntry(h); + exif_data_unref(exifdata); } - DiscardData(); } checkAndClearExceptionFromCallback(env, __FUNCTION__); @@ -824,22 +842,16 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK && (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) { - ResetJpgfile(); - // Start with an empty image information structure. - memset(&ImageInfo, 0, sizeof(ImageInfo)); - ImageInfo.FlashUsed = -1; - ImageInfo.MeteringMode = -1; - ImageInfo.Whitebalance = -1; - strncpy(ImageInfo.FileName, (const char *)path, PATH_MAX); - if (ReadJpegFile((const char*)path, READ_METADATA)) { - Section_t* section = FindSection(M_EXIF); - if (section) { - outThumbSize = ImageInfo.ThumbnailSize; - result = malloc(outThumbSize); - if (result) - memcpy(result, section->Data + ImageInfo.ThumbnailOffset + 8, outThumbSize); + + ExifData *exifdata = exif_data_new_from_file(path); + if (exifdata) { + if (exifdata->data) { + result = malloc(exifdata->size); + if (result) { + memcpy(result, exifdata->data, exifdata->size); + } } - DiscardData(); + exif_data_unref(exifdata); } } diff --git a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java index 5d8d0d17e9c3..df6fca4c7bc9 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java +++ b/policy/src/com/android/internal/policy/impl/PhoneLayoutInflater.java @@ -24,7 +24,8 @@ import android.view.LayoutInflater; public class PhoneLayoutInflater extends LayoutInflater { private static final String[] sClassPrefixList = { "android.widget.", - "android.webkit." + "android.webkit.", + "android.app." }; /** diff --git a/rs/java/android/renderscript/BaseObj.java b/rs/java/android/renderscript/BaseObj.java index 1a15ce6f2fa4..eee4936a96e3 100644 --- a/rs/java/android/renderscript/BaseObj.java +++ b/rs/java/android/renderscript/BaseObj.java @@ -16,6 +16,8 @@ package android.renderscript; +import java.util.concurrent.locks.ReentrantReadWriteLock; + /** * BaseObj is the base class for all RenderScript objects owned by a RS context. * It is responsible for lifetime management and resource tracking. This class @@ -107,17 +109,30 @@ public class BaseObj { return mName; } - protected void finalize() throws Throwable { - if (!mDestroyed) { - if(mID != 0 && mRS.isAlive()) { + private void helpDestroy() { + boolean shouldDestroy = false; + synchronized(this) { + if (!mDestroyed) { + shouldDestroy = true; + mDestroyed = true; + } + } + + if (shouldDestroy) { + // must include nObjDestroy in the critical section + ReentrantReadWriteLock.ReadLock rlock = mRS.mRWLock.readLock(); + rlock.lock(); + if(mRS.isAlive()) { mRS.nObjDestroy(mID); } + rlock.unlock(); mRS = null; mID = 0; - mDestroyed = true; - //Log.v(RenderScript.LOG_TAG, getClass() + - // " auto finalizing object without having released the RS reference."); } + } + + protected void finalize() throws Throwable { + helpDestroy(); super.finalize(); } @@ -126,12 +141,11 @@ public class BaseObj { * primary use is to force immediate cleanup of resources when it is * believed the GC will not respond quickly enough. */ - synchronized public void destroy() { + public void destroy() { if(mDestroyed) { throw new RSInvalidStateException("Object already destroyed."); } - mDestroyed = true; - mRS.nObjDestroy(mID); + helpDestroy(); } /** diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java index d2c74564db80..b0ef156e0934 100644 --- a/rs/java/android/renderscript/RenderScript.java +++ b/rs/java/android/renderscript/RenderScript.java @@ -18,6 +18,7 @@ package android.renderscript; import java.io.File; import java.lang.reflect.Method; +import java.util.concurrent.locks.ReentrantReadWriteLock; import android.content.Context; import android.content.res.AssetManager; @@ -147,6 +148,7 @@ public class RenderScript { } ContextType mContextType; + ReentrantReadWriteLock mRWLock; // Methods below are wrapped to protect the non-threadsafe // lockless fifo. @@ -174,7 +176,18 @@ public class RenderScript { native void rsnContextDestroy(long con); synchronized void nContextDestroy() { validate(); - rsnContextDestroy(mContext); + + // take teardown lock + // teardown lock can only be taken when no objects are being destroyed + ReentrantReadWriteLock.WriteLock wlock = mRWLock.writeLock(); + wlock.lock(); + + long curCon = mContext; + // context is considered dead as of this point + mContext = 0; + + wlock.unlock(); + rsnContextDestroy(curCon); } native void rsnContextSetSurface(long con, int w, int h, Surface sur); synchronized void nContextSetSurface(int w, int h, Surface sur) { @@ -259,8 +272,10 @@ public class RenderScript { validate(); return rsnGetName(mContext, obj); } + + // nObjDestroy is explicitly _not_ synchronous to prevent crashes in finalizers native void rsnObjDestroy(long con, long id); - synchronized void nObjDestroy(long id) { + void nObjDestroy(long id) { // There is a race condition here. The calling code may be run // by the gc while teardown is occuring. This protects againts // deleting dead objects. @@ -1092,6 +1107,7 @@ public class RenderScript { if (ctx != null) { mApplicationContext = ctx.getApplicationContext(); } + mRWLock = new ReentrantReadWriteLock(); } /** @@ -1186,6 +1202,8 @@ public class RenderScript { */ public void destroy() { validate(); + nContextFinish(); + nContextDeinitToClient(mContext); mMessageThread.mRun = false; try { @@ -1194,7 +1212,6 @@ public class RenderScript { } nContextDestroy(); - mContext = 0; nDeviceDestroy(mDev); mDev = 0; diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp index 84d9a22443bf..5cf3a83b19c6 100644 --- a/rs/jni/android_renderscript_RenderScript.cpp +++ b/rs/jni/android_renderscript_RenderScript.cpp @@ -224,28 +224,28 @@ nDeviceCreate(JNIEnv *_env, jobject _this) } static void -nDeviceDestroy(JNIEnv *_env, jobject _this, jint dev) +nDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev) { LOG_API("nDeviceDestroy"); return rsDeviceDestroy((RsDevice)dev); } static void -nDeviceSetConfig(JNIEnv *_env, jobject _this, jint dev, jint p, jint value) +nDeviceSetConfig(JNIEnv *_env, jobject _this, jlong dev, jint p, jint value) { LOG_API("nDeviceSetConfig dev(%p), param(%i), value(%i)", (void *)dev, p, value); return rsDeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value); } static jlong -nContextCreate(JNIEnv *_env, jobject _this, jint dev, jint ver, jint sdkVer, jint ct) +nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, jint ct) { LOG_API("nContextCreate"); return (jint)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0); } static jlong -nContextCreateGL(JNIEnv *_env, jobject _this, jint dev, jint ver, jint sdkVer, +nContextCreateGL(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, int colorMin, int colorPref, int alphaMin, int alphaPref, int depthMin, int depthPref, diff --git a/services/Android.mk b/services/Android.mk index 553159289b8f..80fd35a0e345 100644 --- a/services/Android.mk +++ b/services/Android.mk @@ -43,4 +43,7 @@ LOCAL_MODULE:= libandroid_servers include $(BUILD_SHARED_LIBRARY) +ifeq (,$(ONE_SHOT_MAKEFILE)) include $(call all-makefiles-under, $(LOCAL_PATH)) +endif + diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 125621a20a9c..6078611f6983 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -458,11 +458,11 @@ final class ActivityStack { final void moveToFront() { if (isAttached()) { - mStacks.remove(this); - mStacks.add(this); if (isOnHomeDisplay()) { mStackSupervisor.moveHomeStack(isHomeStack()); } + mStacks.remove(this); + mStacks.add(this); } } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 1e0be233ee19..5e8c52c18edd 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -59,6 +59,8 @@ import android.content.res.Configuration; import android.graphics.Point; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManager.DisplayListener; +import android.hardware.display.DisplayManagerGlobal; +import android.hardware.display.VirtualDisplay; import android.os.Binder; import android.os.Bundle; import android.os.Debug; @@ -79,6 +81,7 @@ import android.util.SparseArray; import android.util.SparseIntArray; import android.view.Display; import android.view.DisplayInfo; +import android.view.Surface; import com.android.internal.app.HeavyWeightSwitcherActivity; import com.android.internal.os.TransferPipe; import com.android.server.am.ActivityManagerService.PendingActivityLaunch; @@ -88,6 +91,7 @@ import com.android.server.wm.WindowManagerService; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; @@ -119,6 +123,7 @@ public final class ActivityStackSupervisor implements DisplayListener { static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6; static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7; + private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay"; // For debugging to make sure the caller when acquiring/releasing our // wake lock is the system process. @@ -212,11 +217,13 @@ public final class ActivityStackSupervisor implements DisplayListener { /** Stack id of the front stack when user switched, indexed by userId. */ SparseIntArray mUserStackInFront = new SparseIntArray(2); + // TODO: Add listener for removal of references. /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */ - SparseArray<ActivityContainer> mActivityContainers = new SparseArray<ActivityContainer>(); + SparseArray<WeakReference<ActivityContainer>> mActivityContainers = + new SparseArray<WeakReference<ActivityContainer>>(); /** Mapping from displayId to display current state */ - SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>(); + private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>(); public ActivityStackSupervisor(ActivityManagerService service) { mService = service; @@ -2099,9 +2106,14 @@ public final class ActivityStackSupervisor implements DisplayListener { } ActivityStack getStack(int stackId) { - ActivityContainer activityContainer = mActivityContainers.get(stackId); - if (activityContainer != null) { - return activityContainer.mStack; + WeakReference<ActivityContainer> weakReference = mActivityContainers.get(stackId); + if (weakReference != null) { + ActivityContainer activityContainer = weakReference.get(); + if (activityContainer != null) { + return activityContainer.mStack; + } else { + mActivityContainers.remove(stackId); + } } return null; } @@ -2135,7 +2147,7 @@ public final class ActivityStackSupervisor implements DisplayListener { IActivityContainerCallback callback) { ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId, callback); - mActivityContainers.put(stackId, activityContainer); + mActivityContainers.put(stackId, new WeakReference<ActivityContainer>(activityContainer)); if (parentActivity != null) { parentActivity.mChildContainers.add(activityContainer.mStack); } @@ -2729,11 +2741,17 @@ public final class ActivityStackSupervisor implements DisplayListener { } public void handleDisplayAddedLocked(int displayId) { + boolean newDisplay; synchronized (mService) { - ActivityDisplay activityDisplay = new ActivityDisplay(displayId); - mActivityDisplays.put(displayId, activityDisplay); + newDisplay = mActivityDisplays.get(displayId) == null; + if (newDisplay) { + ActivityDisplay activityDisplay = new ActivityDisplay(displayId); + mActivityDisplays.put(displayId, activityDisplay); + } + } + if (newDisplay) { + mWindowManager.onDisplayAdded(displayId); } - mWindowManager.onDisplayAdded(displayId); } public void handleDisplayRemovedLocked(int displayId) { @@ -2961,6 +2979,49 @@ public final class ActivityStackSupervisor implements DisplayListener { return this; } + @Override + public void createActivityView(Surface surface, int width, int height, int density) { + DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance(); + VirtualDisplay virtualDisplay; + long ident = Binder.clearCallingIdentity(); + try { + virtualDisplay = dm.createVirtualDisplay(mService.mContext, + VIRTUAL_DISPLAY_BASE_NAME, width, height, density, surface, + // TODO: Add VIRTUAL_DISPLAY_FLAG_DISABLE_MIRRORING when it is available. + DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC); + } finally { + Binder.restoreCallingIdentity(ident); + } + + final Display display = virtualDisplay.getDisplay(); + final int displayId = display.getDisplayId(); + + // Do WindowManager operation first so that it is ahead of CREATE_STACK in the H queue. + mWindowManager.onDisplayAdded(displayId); + + synchronized (mService) { + ActivityDisplay activityDisplay = new ActivityDisplay(display); + mActivityDisplays.put(displayId, activityDisplay); + attachToDisplayLocked(activityDisplay); + activityDisplay.mVirtualDisplay = virtualDisplay; + } + } + + @Override + public void deleteActivityView() { + synchronized (mService) { + if (!isAttached()) { + return; + } + VirtualDisplay virtualDisplay = mActivityDisplay.mVirtualDisplay; + if (virtualDisplay != null) { + virtualDisplay.release(); + mActivityDisplay.mVirtualDisplay = null; + } + detachLocked(); + } + } + ActivityStackSupervisor getOuter() { return ActivityStackSupervisor.this; } @@ -2990,9 +3051,17 @@ public final class ActivityStackSupervisor implements DisplayListener { * stacks, bottommost behind. Accessed directly by ActivityManager package classes */ final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>(); + /** If this display is for an ActivityView then the VirtualDisplay created for it is stored + * here. */ + VirtualDisplay mVirtualDisplay; + ActivityDisplay(int displayId) { - mDisplayId = displayId; - mDisplay = mDisplayManager.getDisplay(displayId); + this(mDisplayManager.getDisplay(displayId)); + } + + ActivityDisplay(Display display) { + mDisplay = display; + mDisplayId = display.getDisplayId(); mDisplay.getDisplayInfo(mDisplayInfo); } diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index 073e24a30518..12ef65ae6eba 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -31,6 +31,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; @@ -675,7 +676,8 @@ public final class DisplayManagerService extends IDisplayManager.Stub { if (surface == null) { throw new IllegalArgumentException("surface must not be null"); } - if ((flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { + if (callingUid != Process.SYSTEM_UID && + (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) { if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT) != PackageManager.PERMISSION_GRANTED && mContext.checkCallingPermission( diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index b71fc1996e26..ca8ff1edd688 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -4816,21 +4816,23 @@ public class WindowManagerService extends IWindowManager.Stub } /** - * Create a new TaskStack and place it next to an existing stack. + * Create a new TaskStack and place it on a DisplayContent. * @param stackId The unique identifier of the new stack. + * @param displayId The unique identifier of the DisplayContent. */ public void createStack(int stackId, int displayId) { - synchronized (mWindowMap) { - final int numDisplays = mDisplayContents.size(); - for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { - final DisplayContent displayContent = mDisplayContents.valueAt(displayNdx); - if (displayContent.getDisplayId() == displayId) { + final long origId = Binder.clearCallingIdentity(); + try { + synchronized (mWindowMap) { + final DisplayContent displayContent = mDisplayContents.get(displayId); + if (displayContent != null) { TaskStack stack = displayContent.createStack(stackId); mStackIdToStack.put(stackId, stack); performLayoutAndPlaceSurfacesLocked(); - return; } } + } finally { + Binder.restoreCallingIdentity(origId); } } @@ -7040,6 +7042,8 @@ public class WindowManagerService extends IWindowManager.Stub public static final int TAP_OUTSIDE_STACK = 31; public static final int NOTIFY_ACTIVITY_DRAWN = 32; + public static final int REMOVE_STARTING_TIMEOUT = 33; + @Override public void handleMessage(Message msg) { if (DEBUG_WINDOW_TRACE) { |