diff options
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/os/Build.java | 34 | ||||
-rw-r--r-- | core/java/android/preference/SeekBarVolumizer.java | 23 | ||||
-rw-r--r-- | core/java/android/text/Hyphenator.java | 48 | ||||
-rw-r--r-- | core/java/android/text/StaticLayout.java | 6 | ||||
-rw-r--r-- | core/java/android/view/Window.java | 29 | ||||
-rw-r--r-- | core/java/com/android/internal/app/ChooserActivity.java | 25 |
6 files changed, 122 insertions, 43 deletions
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 2374899..862f4c4 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -577,7 +577,7 @@ public class Build { public static final int KITKAT = 19; /** - * Android 4.4W: KitKat for watches, snacks on the run. + * June 2014: Android 4.4W. KitKat for watches, snacks on the run. * * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> @@ -595,7 +595,7 @@ public class Build { public static final int L = 21; /** - * Lollipop. A flat one with beautiful shadows. But still tasty. + * November 2014: Lollipop. A flat one with beautiful shadows. But still tasty. * * <p>Applications targeting this or a later release will get these * new changes in behavior:</p> @@ -626,12 +626,38 @@ public class Build { public static final int LOLLIPOP = 21; /** - * Lollipop with an extra sugar coating on the outside! + * March 2015: Lollipop with an extra sugar coating on the outside! */ public static final int LOLLIPOP_MR1 = 22; /** - * M comes after L. + * M is for Marshmallow! + * + * <p>Applications targeting this or a later release will get these + * new changes in behavior:</p> + * <ul> + * <li> Runtime permissions. Dangerous permissions are no longer granted at + * install time, but must be requested by the application at runtime through + * {@link android.app.Activity#requestPermissions}.</li> + * <li> Bluetooth and Wi-Fi scanning now requires holding the location permission.</li> + * <li> {@link android.app.AlarmManager#setTimeZone AlarmManager.setTimeZone} will fail if + * the given timezone is non-Olson.</li> + * <li> Activity transitions will only return shared + * elements mapped in the returned view hierarchy back to the calling activity.</li> + * <li> {@link android.view.View} allows a number of behaviors that may break + * existing apps: Canvas throws an exception if restore() is called too many times, + * widgets may return a hint size when returning UNSPECIFIED measure specs, and it + * will respect the attributes {@link android.R.attr#foreground}, + * {@link android.R.attr#foregroundGravity}, {@link android.R.attr#foregroundTint}, and + * {@link android.R.attr#foregroundTintMode}.</li> + * <li> {@link android.view.MotionEvent#getButtonState MotionEvent.getButtonState} + * will no longer report {@link android.view.MotionEvent#BUTTON_PRIMARY} + * and {@link android.view.MotionEvent#BUTTON_SECONDARY} as synonyms for + * {@link android.view.MotionEvent#BUTTON_STYLUS_PRIMARY} and + * {@link android.view.MotionEvent#BUTTON_STYLUS_SECONDARY}.</li> + * <li> {@link android.widget.ScrollView} now respects the layout param margins + * when measuring.</li> + * </ul> */ public static final int M = 23; } diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java index 979c828..2445bc2 100644 --- a/core/java/android/preference/SeekBarVolumizer.java +++ b/core/java/android/preference/SeekBarVolumizer.java @@ -383,6 +383,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba final IntentFilter filter = new IntentFilter(AudioManager.VOLUME_CHANGED_ACTION); filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); filter.addAction(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); + filter.addAction(AudioManager.STREAM_DEVICES_CHANGED_ACTION); mContext.registerReceiver(this, filter); } else { mContext.unregisterReceiver(this); @@ -395,13 +396,7 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) { int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1); - final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType) - : (streamType == mStreamType); - if (mSeekBar != null && streamMatch && streamValue != -1) { - final boolean muted = mAudioManager.isStreamMute(mStreamType) - || streamValue == 0; - mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted); - } + updateVolumeSlider(streamType, streamValue); } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { if (mNotificationOrRing) { mRingerMode = mAudioManager.getRingerModeInternal(); @@ -409,10 +404,24 @@ public class SeekBarVolumizer implements OnSeekBarChangeListener, Handler.Callba if (mAffectedByRingerMode) { updateSlider(); } + } else if (AudioManager.STREAM_DEVICES_CHANGED_ACTION.equals(action)) { + int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1); + int streamVolume = mAudioManager.getStreamVolume(streamType); + updateVolumeSlider(streamType, streamVolume); } else if (NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED.equals(action)) { mZenMode = mNotificationManager.getZenMode(); updateSlider(); } } + + private void updateVolumeSlider(int streamType, int streamValue) { + final boolean streamMatch = mNotificationOrRing ? isNotificationOrRing(streamType) + : (streamType == mStreamType); + if (mSeekBar != null && streamMatch && streamValue != -1) { + final boolean muted = mAudioManager.isStreamMute(mStreamType) + || streamValue == 0; + mUiHandler.postUpdateSlider(streamValue, mLastAudibleStreamVolume, muted); + } + } } } diff --git a/core/java/android/text/Hyphenator.java b/core/java/android/text/Hyphenator.java index 10a994a..f2b6041 100644 --- a/core/java/android/text/Hyphenator.java +++ b/core/java/android/text/Hyphenator.java @@ -16,15 +16,17 @@ package android.text; -import com.android.internal.annotations.GuardedBy; - import android.annotation.Nullable; import android.util.Log; -import libcore.io.IoUtils; +import com.android.internal.annotations.GuardedBy; import java.io.File; import java.io.IOException; +import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.MappedByteBuffer; +import java.nio.channels.FileChannel; import java.util.HashMap; import java.util.Locale; @@ -45,19 +47,29 @@ public class Hyphenator { @GuardedBy("sLock") final static HashMap<Locale, Hyphenator> sMap = new HashMap<Locale, Hyphenator>(); - final static Hyphenator sEmptyHyphenator = new Hyphenator(StaticLayout.nLoadHyphenator("")); + final static Hyphenator sEmptyHyphenator = + new Hyphenator(StaticLayout.nLoadHyphenator(null, 0), null); final private long mNativePtr; - private Hyphenator(long nativePtr) { + // We retain a reference to the buffer to keep the memory mapping valid + @SuppressWarnings("unused") + final private ByteBuffer mBuffer; + + private Hyphenator(long nativePtr, ByteBuffer b) { mNativePtr = nativePtr; + mBuffer = b; } - public static long get(@Nullable Locale locale) { + public long getNativePtr() { + return mNativePtr; + } + + public static Hyphenator get(@Nullable Locale locale) { synchronized (sLock) { Hyphenator result = sMap.get(locale); if (result != null) { - return result.mNativePtr; + return result; } // TODO: Convert this a proper locale-fallback system @@ -67,7 +79,7 @@ public class Hyphenator { result = sMap.get(languageOnlyLocale); if (result != null) { sMap.put(locale, result); - return result.mNativePtr; + return result; } // Fall back to script-only, if available @@ -80,22 +92,28 @@ public class Hyphenator { result = sMap.get(scriptOnlyLocale); if (result != null) { sMap.put(locale, result); - return result.mNativePtr; + return result; } } sMap.put(locale, sEmptyHyphenator); // To remember we found nothing. } - return sEmptyHyphenator.mNativePtr; + return sEmptyHyphenator; } private static Hyphenator loadHyphenator(String languageTag) { - String patternFilename = "hyph-"+languageTag.toLowerCase(Locale.US)+".pat.txt"; + String patternFilename = "hyph-" + languageTag.toLowerCase(Locale.US) + ".hyb"; File patternFile = new File(getSystemHyphenatorLocation(), patternFilename); try { - String patternData = IoUtils.readFileAsString(patternFile.getAbsolutePath()); - long nativePtr = StaticLayout.nLoadHyphenator(patternData); - return new Hyphenator(nativePtr); + RandomAccessFile f = new RandomAccessFile(patternFile, "r"); + try { + FileChannel fc = f.getChannel(); + MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); + long nativePtr = StaticLayout.nLoadHyphenator(buf, 0); + return new Hyphenator(nativePtr, buf); + } finally { + f.close(); + } } catch (IOException e) { Log.e(TAG, "error loading hyphenation " + patternFile, e); return null; @@ -148,7 +166,7 @@ public class Hyphenator { sMap.put(null, null); // TODO: replace this with a discovery-based method that looks into /system/usr/hyphen-data - String[] availableLanguages = {"en-US", "eu", "hu", "hy", "nb", "nn", "sa", "und-Ethi"}; + String[] availableLanguages = {"en-US", "eu", "hu", "hy", "nb", "nn", "und-Ethi"}; for (int i = 0; i < availableLanguages.length; i++) { String languageTag = availableLanguages[i]; Hyphenator h = loadHyphenator(languageTag); diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 3b0def2..b0b08db 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -29,6 +29,7 @@ import android.util.Pools.SynchronizedPool; import com.android.internal.util.ArrayUtils; import com.android.internal.util.GrowingArrayUtils; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Locale; @@ -341,7 +342,8 @@ public class StaticLayout extends Layout { private void setLocale(Locale locale) { if (!locale.equals(mLocale)) { - nSetLocale(mNativePtr, locale.toLanguageTag(), Hyphenator.get(locale)); + nSetLocale(mNativePtr, locale.toLanguageTag(), + Hyphenator.get(locale).getNativePtr()); mLocale = locale; } } @@ -1243,7 +1245,7 @@ public class StaticLayout extends Layout { private static native void nFreeBuilder(long nativePtr); private static native void nFinishBuilder(long nativePtr); - /* package */ static native long nLoadHyphenator(String patternData); + /* package */ static native long nLoadHyphenator(ByteBuffer buf, int offset); private static native void nSetLocale(long nativePtr, String locale, long nativeHyphenator); diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 07984e9..c222a82 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -578,7 +578,7 @@ public abstract class Window { void adjustLayoutParamsForSubWindow(WindowManager.LayoutParams wp) { CharSequence curTitle = wp.getTitle(); if (wp.type >= WindowManager.LayoutParams.FIRST_SUB_WINDOW && - wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { + wp.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) { if (wp.token == null) { View decor = peekDecorView(); if (decor != null) { @@ -588,25 +588,38 @@ public abstract class Window { if (curTitle == null || curTitle.length() == 0) { String title; if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA) { - title="Media"; + title = "Media"; } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY) { - title="MediaOvr"; + title = "MediaOvr"; } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) { - title="Panel"; + title = "Panel"; } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) { - title="SubPanel"; + title = "SubPanel"; } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL) { - title="AboveSubPanel"; + title = "AboveSubPanel"; } else if (wp.type == WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG) { - title="AtchDlg"; + title = "AtchDlg"; } else { - title=Integer.toString(wp.type); + title = Integer.toString(wp.type); } if (mAppName != null) { title += ":" + mAppName; } wp.setTitle(title); } + } else if (wp.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW && + wp.type <= WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) { + // We don't set the app token to this system window because the life cycles should be + // independent. If an app creates a system window and then the app goes to the stopped + // state, the system window should not be affected (can still show and receive input + // events). + if (curTitle == null || curTitle.length() == 0) { + String title = "Sys" + Integer.toString(wp.type); + if (mAppName != null) { + title += ":" + mAppName; + } + wp.setTitle(title); + } } else { if (wp.token == null) { wp.token = mContainer == null ? mAppToken : mContainer.mAppToken; diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index 6bbebb7..9708cce 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -1017,7 +1017,15 @@ public class ChooserActivity extends ResolverActivity { final RowScale rs = new RowScale(ChooserRowAdapter.this, 0.f, 1.f) .setInterpolator(mInterpolator); mServiceTargetScale[i] = rs; - rs.startAnimation(); + } + + // Start the animations in a separate loop. + // The process of starting animations will result in + // binding views to set up initial values, and we must + // have ALL of the new RowScale objects created above before + // we get started. + for (int i = oldRCount; i < rcount; i++) { + mServiceTargetScale[i].startAnimation(); } } @@ -1097,17 +1105,19 @@ public class ChooserActivity extends ResolverActivity { for (int i = 0; i < mColumnCount; i++) { final View v = mChooserListAdapter.createView(row); + final int column = i; v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { - startSelected(holder.itemIndex, false, true); + startSelected(holder.itemIndices[column], false, true); } }); v.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { showAppDetails( - mChooserListAdapter.resolveInfoForPosition(holder.itemIndex, true)); + mChooserListAdapter.resolveInfoForPosition( + holder.itemIndices[column], true)); return true; } }); @@ -1165,8 +1175,8 @@ public class ChooserActivity extends ResolverActivity { final View v = holder.cells[i]; if (start + i <= end) { v.setVisibility(View.VISIBLE); - holder.itemIndex = start + i; - mChooserListAdapter.bindView(holder.itemIndex, v); + holder.itemIndices[i] = start + i; + mChooserListAdapter.bindView(holder.itemIndices[i], v); } else { v.setVisibility(View.GONE); } @@ -1197,11 +1207,12 @@ public class ChooserActivity extends ResolverActivity { final View[] cells; final ViewGroup row; int measuredRowHeight; - int itemIndex; + int[] itemIndices; public RowViewHolder(ViewGroup row, int cellCount) { this.row = row; this.cells = new View[cellCount]; + this.itemIndices = new int[cellCount]; } public void measure() { @@ -1389,7 +1400,7 @@ public class ChooserActivity extends ResolverActivity { final View v = mChooserRowAdapter.getView(pos, mCachedView, mListView); int height = ((RowViewHolder) (v.getTag())).measuredRowHeight; - offset += (int) (height * mChooserRowAdapter.getRowScale(pos) * chooserTargetRows); + offset += (int) (height * mChooserRowAdapter.getRowScale(pos)); if (vt >= 0) { mCachedViewType = vt; |