summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/animation/PropertyValuesHolder.java32
-rw-r--r--core/java/android/app/Activity.java2
-rw-r--r--core/java/android/app/ActivityOptions.java5
-rw-r--r--core/java/android/app/Dialog.java10
-rw-r--r--core/java/android/app/Notification.java146
-rw-r--r--core/java/android/content/AbstractThreadedSyncAdapter.java9
-rw-r--r--core/java/android/content/Intent.java12
-rw-r--r--core/java/android/content/SyncManager.java58
-rw-r--r--core/java/android/content/SyncOperation.java4
-rw-r--r--core/java/android/content/SyncStorageEngine.java4
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java1
-rw-r--r--core/java/android/content/pm/PackageParser.java2
-rw-r--r--core/java/android/hardware/Camera.java131
-rw-r--r--core/java/android/net/INetworkStatsService.aidl2
-rw-r--r--core/java/android/net/NetworkIdentity.java11
-rw-r--r--core/java/android/net/NetworkState.java8
-rw-r--r--core/java/android/os/ConditionVariable.java2
-rw-r--r--core/java/android/os/HandlerThread.java2
-rw-r--r--core/java/android/os/INetworkManagementService.aidl3
-rw-r--r--core/java/android/os/Message.java4
-rw-r--r--core/java/android/os/Trace.java1
-rw-r--r--core/java/android/provider/CallLog.java9
-rw-r--r--core/java/android/provider/SocialContract.java187
-rw-r--r--core/java/android/service/textservice/SpellCheckerService.java8
-rw-r--r--core/java/android/text/SpannableStringBuilder.java19
-rw-r--r--core/java/android/text/TextDirectionHeuristics.java1
-rw-r--r--core/java/android/util/LocaleUtil.java7
-rw-r--r--core/java/android/util/MathUtils.java4
-rw-r--r--core/java/android/view/Display.java9
-rw-r--r--core/java/android/view/DisplayList.java8
-rw-r--r--core/java/android/view/FocusFinder.java52
-rw-r--r--core/java/android/view/Gravity.java4
-rw-r--r--core/java/android/view/HardwareRenderer.java2
-rw-r--r--core/java/android/view/View.java143
-rw-r--r--core/java/android/view/ViewGroup.java25
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java22
-rw-r--r--core/java/android/view/ViewRootImpl.java67
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java43
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java150
-rw-r--r--core/java/android/webkit/AutoCompletePopup.java47
-rw-r--r--core/java/android/webkit/BrowserFrame.java27
-rw-r--r--core/java/android/webkit/ClientCertRequestHandler.java51
-rw-r--r--core/java/android/webkit/SslClientCertLookupTable.java9
-rw-r--r--core/java/android/webkit/WebViewClassic.java78
-rw-r--r--core/java/android/webkit/WebViewInputDispatcher.java90
-rw-r--r--core/java/android/widget/ActivityChooserModel.java10
-rw-r--r--core/java/android/widget/ActivityChooserView.java46
-rwxr-xr-xcore/java/android/widget/AppSecurityPermissions.java632
-rw-r--r--core/java/android/widget/CalendarView.java52
-rw-r--r--core/java/android/widget/ImageView.java3
-rw-r--r--core/java/android/widget/LinearLayout.java4
-rw-r--r--core/java/android/widget/ProgressBar.java39
-rw-r--r--core/java/android/widget/RemoteViews.java8
-rw-r--r--core/java/android/widget/SearchView.java4
-rw-r--r--core/java/android/widget/ShareActionProvider.java7
-rw-r--r--core/java/android/widget/SpellChecker.java144
-rw-r--r--core/java/android/widget/TextView.java11
-rw-r--r--core/java/com/android/internal/app/ActionBarImpl.java158
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java164
-rw-r--r--core/java/com/android/internal/net/NetworkStatsFactory.java165
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java2
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuItemView.java16
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuView.java20
-rw-r--r--core/java/com/android/internal/widget/ActionBarOverlayLayout.java31
64 files changed, 1865 insertions, 1162 deletions
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java
index 58f23f7..5b1a7cf 100644
--- a/core/java/android/animation/PropertyValuesHolder.java
+++ b/core/java/android/animation/PropertyValuesHolder.java
@@ -384,8 +384,7 @@ public class PropertyValuesHolder implements Cloneable {
try {
returnVal = targetClass.getMethod(methodName, args);
} catch (NoSuchMethodException e) {
- Log.e("PropertyValuesHolder",
- "Couldn't find no-arg method for property " + mPropertyName + ": " + e);
+ // Swallow the error, log it later
}
} else {
args = new Class[1];
@@ -412,9 +411,12 @@ public class PropertyValuesHolder implements Cloneable {
}
}
// If we got here, then no appropriate function was found
- Log.e("PropertyValuesHolder",
- "Couldn't find setter/getter for property " + mPropertyName +
- " with value type "+ mValueType);
+ }
+
+ if (returnVal == null) {
+ Log.w("PropertyValuesHolder", "Method " +
+ getMethodName(prefix, mPropertyName) + "() with type " + mValueType +
+ " not found on target class " + targetClass);
}
return returnVal;
@@ -495,7 +497,7 @@ public class PropertyValuesHolder implements Cloneable {
}
return;
} catch (ClassCastException e) {
- Log.e("PropertyValuesHolder","No such property (" + mProperty.getName() +
+ Log.w("PropertyValuesHolder","No such property (" + mProperty.getName() +
") on target object " + target + ". Trying reflection instead");
mProperty = null;
}
@@ -508,6 +510,10 @@ public class PropertyValuesHolder implements Cloneable {
if (!kf.hasValue()) {
if (mGetter == null) {
setupGetter(targetClass);
+ if (mGetter == null) {
+ // Already logged the error - just return to avoid NPE
+ return;
+ }
}
try {
kf.setValue(mGetter.invoke(target));
@@ -535,6 +541,10 @@ public class PropertyValuesHolder implements Cloneable {
if (mGetter == null) {
Class targetClass = target.getClass();
setupGetter(targetClass);
+ if (mGetter == null) {
+ // Already logged the error - just return to avoid NPE
+ return;
+ }
}
kf.setValue(mGetter.invoke(target));
} catch (InvocationTargetException e) {
@@ -854,8 +864,9 @@ public class PropertyValuesHolder implements Cloneable {
}
}
} catch (NoSuchMethodError e) {
- Log.d("PropertyValuesHolder",
- "Can't find native method using JNI, use reflection" + e);
+ // Couldn't find it via JNI - try reflection next. Probably means the method
+ // doesn't exist, or the type is wrong. An error will be logged later if
+ // reflection fails as well.
} finally {
mPropertyMapLock.writeLock().unlock();
}
@@ -990,8 +1001,9 @@ public class PropertyValuesHolder implements Cloneable {
}
}
} catch (NoSuchMethodError e) {
- Log.d("PropertyValuesHolder",
- "Can't find native method using JNI, use reflection" + e);
+ // Couldn't find it via JNI - try reflection next. Probably means the method
+ // doesn't exist, or the type is wrong. An error will be logged later if
+ // reflection fails as well.
} finally {
mPropertyMapLock.writeLock().unlock();
}
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8d6a496..29d96fe 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1242,7 +1242,7 @@ public class Activity extends ContextThemeWrapper
* making sure nothing is lost if there are not enough resources to start
* the new activity without first killing this one. This is also a good
* place to do things like stop animations and other things that consume a
- * noticeable mount of CPU in order to make the switch to the next activity
+ * noticeable amount of CPU in order to make the switch to the next activity
* as fast as possible, or to close resources that are exclusive access
* such as the camera.
*
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 423b02a..b730581 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -325,10 +325,11 @@ public class ActivityOptions {
}
/**
- * Join the values in <var>otherOptions</var> in to this one. Any values
+ * Update the current values in this ActivityOptions from those supplied
+ * in <var>otherOptions</var>. Any values
* defined in <var>otherOptions</var> replace those in the base options.
*/
- public void join(ActivityOptions otherOptions) {
+ public void update(ActivityOptions otherOptions) {
if (otherOptions.mPackageName != null) {
mPackageName = otherOptions.mPackageName;
}
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index f04ff6a..2cc3b02 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -27,6 +27,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.util.TypedValue;
@@ -103,7 +104,6 @@ public class Dialog implements DialogInterface, Window.Callback,
private boolean mShowing = false;
private boolean mCanceled = false;
- private final Thread mUiThread;
private final Handler mHandler = new Handler();
private static final int DISMISS = 0x43;
@@ -162,7 +162,6 @@ public class Dialog implements DialogInterface, Window.Callback,
w.setCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
- mUiThread = Thread.currentThread();
mListenersHandler = new ListenersHandler(this);
}
@@ -299,11 +298,10 @@ public class Dialog implements DialogInterface, Window.Callback,
* that in {@link #onStop}.
*/
public void dismiss() {
- if (Thread.currentThread() != mUiThread) {
- mHandler.post(mDismissAction);
+ if (Looper.myLooper() == mHandler.getLooper()) {
+ dismissDialog();
} else {
- mHandler.removeCallbacks(mDismissAction);
- mDismissAction.run();
+ mHandler.post(mDismissAction);
}
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 8f4efab..0d76877 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -806,6 +806,10 @@ public class Notification implements Parcelable
contentView.setViewVisibility(R.id.time, View.VISIBLE);
contentView.setLong(R.id.time, "setTime", when);
}
+ if (this.number != 0) {
+ NumberFormat f = NumberFormat.getIntegerInstance();
+ contentView.setTextViewText(R.id.info, f.format(this.number));
+ }
this.contentView = contentView;
this.contentIntent = contentIntent;
@@ -1397,7 +1401,8 @@ public class Notification implements Parcelable
if (mSubText != null) {
contentView.setTextViewText(R.id.text, mSubText);
- contentView.setViewVisibility(R.id.text2, View.VISIBLE);
+ contentView.setViewVisibility(R.id.text2,
+ mContentText != null ? View.VISIBLE : View.GONE);
} else {
contentView.setViewVisibility(R.id.text2, View.GONE);
if (mProgressMax != 0 || mProgressIndeterminate) {
@@ -1428,12 +1433,12 @@ public class Notification implements Parcelable
int N = mActions.size();
if (N > 0) {
- Log.d("Notification", "has actions: " + mContentText);
+ // Log.d("Notification", "has actions: " + mContentText);
big.setViewVisibility(R.id.actions, View.VISIBLE);
if (N>3) N=3;
for (int i=0; i<N; i++) {
final RemoteViews button = generateActionButton(mActions.get(i));
- Log.d("Notification", "adding action " + i + ": " + mActions.get(i).title);
+ //Log.d("Notification", "adding action " + i + ": " + mActions.get(i).title);
big.addView(R.id.actions, button);
}
}
@@ -1549,9 +1554,28 @@ public class Notification implements Parcelable
* An object that can apply a rich notification style to a {@link Notification.Builder}
* object.
*/
- public static class Style {
+ public static abstract class Style
+ {
+ private CharSequence mBigContentTitle;
+ private CharSequence mSummaryText = null;
+
protected Builder mBuilder;
+ /**
+ * Overrides ContentTitle in the big form of the template.
+ * This defaults to the value passed to setContentTitle().
+ */
+ protected void internalSetBigContentTitle(CharSequence title) {
+ mBigContentTitle = title;
+ }
+
+ /**
+ * Set the first line of text after the detail section in the big form of the template.
+ */
+ protected void internalSetSummaryText(CharSequence cs) {
+ mSummaryText = cs;
+ }
+
public void setBuilder(Builder builder) {
if (mBuilder != builder) {
mBuilder = builder;
@@ -1559,12 +1583,42 @@ public class Notification implements Parcelable
}
}
- public Notification build() {
+ protected void checkBuilder() {
if (mBuilder == null) {
throw new IllegalArgumentException("Style requires a valid Builder object");
}
- return mBuilder.buildUnstyled();
}
+
+ protected RemoteViews getStandardView(int layoutId) {
+ checkBuilder();
+
+ if (mBigContentTitle != null) {
+ mBuilder.setContentTitle(mBigContentTitle);
+ }
+
+ if (mBuilder.mSubText == null) {
+ mBuilder.setContentText(null);
+ }
+
+ RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(layoutId);
+
+ if (mBuilder.mSubText == null) {
+ contentView.setViewVisibility(R.id.line3, View.GONE);
+ }
+
+ if (mBigContentTitle != null && mBigContentTitle.equals("")) {
+ contentView.setViewVisibility(R.id.line1, View.GONE);
+ }
+
+ if (mSummaryText != null && !mSummaryText.equals("")) {
+ contentView.setViewVisibility(R.id.overflow_title, View.VISIBLE);
+ contentView.setTextViewText(R.id.overflow_title, mSummaryText);
+ }
+
+ return contentView;
+ }
+
+ public abstract Notification build();
}
/**
@@ -1594,13 +1648,30 @@ public class Notification implements Parcelable
setBuilder(builder);
}
+ /**
+ * Overrides ContentTitle in the big form of the template.
+ * This defaults to the value passed to setContentTitle().
+ */
+ public BigPictureStyle setBigContentTitle(CharSequence title) {
+ internalSetBigContentTitle(title);
+ return this;
+ }
+
+ /**
+ * Set the first line of text after the detail section in the big form of the template.
+ */
+ public BigPictureStyle setSummaryText(CharSequence cs) {
+ internalSetSummaryText(cs);
+ return this;
+ }
+
public BigPictureStyle bigPicture(Bitmap b) {
mPicture = b;
return this;
}
private RemoteViews makeBigContentView() {
- RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(R.layout.notification_template_big_picture);
+ RemoteViews contentView = getStandardView(R.layout.notification_template_big_picture);
contentView.setImageViewBitmap(R.id.big_picture, mPicture);
@@ -1609,9 +1680,7 @@ public class Notification implements Parcelable
@Override
public Notification build() {
- if (mBuilder == null) {
- throw new IllegalArgumentException("Style requires a valid Builder object");
- }
+ checkBuilder();
Notification wip = mBuilder.buildUnstyled();
wip.bigContentView = makeBigContentView();
return wip;
@@ -1645,14 +1714,30 @@ public class Notification implements Parcelable
setBuilder(builder);
}
+ /**
+ * Overrides ContentTitle in the big form of the template.
+ * This defaults to the value passed to setContentTitle().
+ */
+ public BigTextStyle setBigContentTitle(CharSequence title) {
+ internalSetBigContentTitle(title);
+ return this;
+ }
+
+ /**
+ * Set the first line of text after the detail section in the big form of the template.
+ */
+ public BigTextStyle setSummaryText(CharSequence cs) {
+ internalSetSummaryText(cs);
+ return this;
+ }
+
public BigTextStyle bigText(CharSequence cs) {
mBigText = cs;
return this;
}
private RemoteViews makeBigContentView() {
- int bigTextId = R.layout.notification_template_big_text;
- RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(bigTextId);
+ RemoteViews contentView = getStandardView(R.layout.notification_template_big_text);
contentView.setTextViewText(R.id.big_text, mBigText);
contentView.setViewVisibility(R.id.big_text, View.VISIBLE);
contentView.setViewVisibility(R.id.text2, View.GONE);
@@ -1662,9 +1747,7 @@ public class Notification implements Parcelable
@Override
public Notification build() {
- if (mBuilder == null) {
- throw new IllegalArgumentException("Style requires a valid Builder object");
- }
+ checkBuilder();
Notification wip = mBuilder.buildUnstyled();
wip.bigContentView = makeBigContentView();
return wip;
@@ -1678,12 +1761,14 @@ public class Notification implements Parcelable
* <pre class="prettyprint">
* Notification noti = new Notification.InboxStyle(
* new Notification.Builder()
- * .setContentTitle(&quot;New mail from &quot; + sender.toString())
+ * .setContentTitle(&quot;5 New mails from &quot; + sender.toString())
* .setContentText(subject)
* .setSmallIcon(R.drawable.new_mail)
* .setLargeIcon(aBitmap))
* .addLine(str1)
* .addLine(str2)
+ * .setContentTitle("")
+ * .setSummaryText(&quot;+3 more&quot;)
* .build();
* </pre>
*
@@ -1699,16 +1784,35 @@ public class Notification implements Parcelable
setBuilder(builder);
}
+ /**
+ * Overrides ContentTitle in the big form of the template.
+ * This defaults to the value passed to setContentTitle().
+ */
+ public InboxStyle setBigContentTitle(CharSequence title) {
+ internalSetBigContentTitle(title);
+ return this;
+ }
+
+ /**
+ * Set the first line of text after the detail section in the big form of the template.
+ */
+ public InboxStyle setSummaryText(CharSequence cs) {
+ internalSetSummaryText(cs);
+ return this;
+ }
+
public InboxStyle addLine(CharSequence cs) {
mTexts.add(cs);
return this;
}
private RemoteViews makeBigContentView() {
- RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(R.layout.notification_template_inbox);
+ RemoteViews contentView = getStandardView(R.layout.notification_template_inbox);
+ contentView.setViewVisibility(R.id.text2, View.GONE);
+
+ int[] rowIds = {R.id.inbox_text0, R.id.inbox_text1, R.id.inbox_text2, R.id.inbox_text3,
+ R.id.inbox_text4};
- int[] rowIds = {R.id.inbox_text0, R.id.inbox_text1, R.id.inbox_text2, R.id.inbox_text3, R.id.inbox_text4};
-
int i=0;
while (i < mTexts.size() && i < rowIds.length) {
CharSequence str = mTexts.get(i);
@@ -1724,9 +1828,7 @@ public class Notification implements Parcelable
@Override
public Notification build() {
- if (mBuilder == null) {
- throw new IllegalArgumentException("Style requires a valid Builder object");
- }
+ checkBuilder();
Notification wip = mBuilder.buildUnstyled();
wip.bigContentView = makeBigContentView();
return wip;
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index 6bffed7..bafe67d 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -21,6 +21,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
+import android.os.Trace;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;
@@ -233,9 +234,15 @@ public abstract class AbstractThreadedSyncAdapter {
mThreadsKey = toSyncKey(account);
}
+ @Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+ // Trace this sync instance. Note, conceptually this should be in
+ // SyncStorageEngine.insertStartSyncEvent(), but the trace functions require unique
+ // threads in order to track overlapping operations, so we'll do it here for now.
+ Trace.traceBegin(Trace.TRACE_TAG_SYNC_MANAGER, mAuthority);
+
SyncResult syncResult = new SyncResult();
ContentProviderClient provider = null;
try {
@@ -250,6 +257,8 @@ public abstract class AbstractThreadedSyncAdapter {
syncResult.databaseError = true;
}
} finally {
+ Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER);
+
if (provider != null) {
provider.release();
}
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index b4669a7..4ed6f25 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1099,6 +1099,14 @@ public class Intent implements Parcelable, Cloneable {
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
/**
+ * Activity Action: Perform assist action.
+ * <p>
+ * Input: nothing
+ * Output: nothing.
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_ASSIST = "android.intent.action.ASSIST";
+ /**
* Activity Action: List all available applications
* <p>Input: Nothing.
* <p>Output: nothing.
@@ -1240,7 +1248,11 @@ public class Intent implements Parcelable, Cloneable {
* Used as a boolean extra field with {@link #ACTION_INSTALL_PACKAGE} to install a
* package. Tells the installer UI to skip the confirmation with the user
* if the .apk is replacing an existing one.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#JELLY_BEAN}, Android
+ * will no longer show an interstitial message about updating existing
+ * applications so this is no longer needed.
*/
+ @Deprecated
public static final String EXTRA_ALLOW_REPLACE
= "android.intent.extra.ALLOW_REPLACE";
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 34c40a0..badcb03 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -17,7 +17,6 @@
package android.content;
import com.android.internal.R;
-import com.android.internal.util.ArrayUtils;
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -32,7 +31,6 @@ import android.app.AppGlobals;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.app.DownloadManager.Request;
import android.content.SyncStorageEngine.OnSyncRequestListener;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -1998,6 +1996,7 @@ public class SyncManager implements OnAccountsUpdateListener {
ActiveSyncContext conflict = null;
ActiveSyncContext longRunning = null;
ActiveSyncContext toReschedule = null;
+ ActiveSyncContext oldestNonExpeditedRegular = null;
for (ActiveSyncContext activeSyncContext : mActiveSyncContexts) {
final SyncOperation activeOp = activeSyncContext.mSyncOperation;
@@ -2005,6 +2004,13 @@ public class SyncManager implements OnAccountsUpdateListener {
numInit++;
} else {
numRegular++;
+ if (!activeOp.isExpedited()) {
+ if (oldestNonExpeditedRegular == null
+ || (oldestNonExpeditedRegular.mStartTime
+ > activeSyncContext.mStartTime)) {
+ oldestNonExpeditedRegular = activeSyncContext;
+ }
+ }
}
if (activeOp.account.type.equals(candidate.account.type)
&& activeOp.authority.equals(candidate.authority)
@@ -2027,8 +2033,13 @@ public class SyncManager implements OnAccountsUpdateListener {
Log.v(TAG, " numActiveInit=" + numInit + ", numActiveRegular=" + numRegular);
Log.v(TAG, " longRunning: " + longRunning);
Log.v(TAG, " conflict: " + conflict);
+ Log.v(TAG, " oldestNonExpeditedRegular: " + oldestNonExpeditedRegular);
}
+ final boolean roomAvailable = candidateIsInitialization
+ ? numInit < MAX_SIMULTANEOUS_INITIALIZATION_SYNCS
+ : numRegular < MAX_SIMULTANEOUS_REGULAR_SYNCS;
+
if (conflict != null) {
if (candidateIsInitialization && !conflict.mSyncOperation.isInitialization()
&& numInit < MAX_SIMULTANEOUS_INITIALIZATION_SYNCS) {
@@ -2048,23 +2059,32 @@ public class SyncManager implements OnAccountsUpdateListener {
} else {
continue;
}
- } else {
- final boolean roomAvailable = candidateIsInitialization
- ? numInit < MAX_SIMULTANEOUS_INITIALIZATION_SYNCS
- : numRegular < MAX_SIMULTANEOUS_REGULAR_SYNCS;
- if (roomAvailable) {
- // dispatch candidate
- } else if (longRunning != null
- && (candidateIsInitialization
- == longRunning.mSyncOperation.isInitialization())) {
- toReschedule = longRunning;
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "canceling and rescheduling sync since it ran roo long, "
- + longRunning);
- }
- } else {
- continue;
+ } else if (roomAvailable) {
+ // dispatch candidate
+ } else if (candidate.isExpedited() && oldestNonExpeditedRegular != null
+ && !candidateIsInitialization) {
+ // We found an active, non-expedited regular sync. We also know that the
+ // candidate doesn't conflict with this active sync since conflict
+ // is null. Reschedule the active sync and start the candidate.
+ toReschedule = oldestNonExpeditedRegular;
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "canceling and rescheduling sync since an expedited is ready to run, "
+ + oldestNonExpeditedRegular);
}
+ } else if (longRunning != null
+ && (candidateIsInitialization
+ == longRunning.mSyncOperation.isInitialization())) {
+ // We found an active, long-running sync. Reschedule the active
+ // sync and start the candidate.
+ toReschedule = longRunning;
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "canceling and rescheduling sync since it ran roo long, "
+ + longRunning);
+ }
+ } else {
+ // we were unable to find or make space to run this candidate, go on to
+ // the next one
+ continue;
}
if (toReschedule != null) {
@@ -2516,7 +2536,7 @@ public class SyncManager implements OnAccountsUpdateListener {
return mSyncStorageEngine.insertStartSyncEvent(
syncOperation.account, syncOperation.userId, syncOperation.authority,
- now, source);
+ now, source, syncOperation.isInitialization());
}
public void stopSyncEvent(long rowId, SyncOperation syncOperation, String resultMessage,
diff --git a/core/java/android/content/SyncOperation.java b/core/java/android/content/SyncOperation.java
index 4e86ef8..9fcc22d 100644
--- a/core/java/android/content/SyncOperation.java
+++ b/core/java/android/content/SyncOperation.java
@@ -116,6 +116,10 @@ public class SyncOperation implements Comparable {
return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
}
+ public boolean isExpedited() {
+ return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
+ }
+
public boolean ignoreBackoff() {
return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
}
diff --git a/core/java/android/content/SyncStorageEngine.java b/core/java/android/content/SyncStorageEngine.java
index d821918..6c7e940 100644
--- a/core/java/android/content/SyncStorageEngine.java
+++ b/core/java/android/content/SyncStorageEngine.java
@@ -221,6 +221,7 @@ public class SyncStorageEngine extends Handler {
long upstreamActivity;
long downstreamActivity;
String mesg;
+ boolean initialization;
}
public static class DayStats {
@@ -1012,7 +1013,7 @@ public class SyncStorageEngine extends Handler {
* Note that sync has started for the given account and authority.
*/
public long insertStartSyncEvent(Account accountName, int userId, String authorityName,
- long now, int source) {
+ long now, int source, boolean initialization) {
long id;
synchronized (mAuthorities) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
@@ -1025,6 +1026,7 @@ public class SyncStorageEngine extends Handler {
return -1;
}
SyncHistoryItem item = new SyncHistoryItem();
+ item.initialization = initialization;
item.authorityId = authority.ident;
item.historyId = mNextHistoryId++;
if (mNextHistoryId < 0) mNextHistoryId = 0;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index cbabc7c..e1434b3 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -298,6 +298,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* activity's manifest.
*
* Default value is false (no support for RTL).
+ * @hide
*/
public static final int FLAG_SUPPORTS_RTL = 1<<22;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 98b40eb..ad52e13 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -1458,7 +1458,7 @@ public class PackageParser {
com.android.internal.R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags, 0);
perm.info.priority = sa.getInt(
com.android.internal.R.styleable.AndroidManifestPermissionGroup_priority, 0);
- if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) != 0) {
+ if (perm.info.priority > 0 && (flags&PARSE_IS_SYSTEM) == 0) {
perm.info.priority = 0;
}
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 5ed8dd1..89068e7 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -155,7 +155,7 @@ public class Camera {
private boolean mOneShot;
private boolean mWithBuffer;
private boolean mFaceDetectionRunning = false;
- private ReentrantLock mFocusLock = new ReentrantLock();
+ private Object mAutoFocusCallbackLock = new Object();
/**
* Broadcast Action: A new picture is taken by the camera, and the entry of
@@ -471,6 +471,11 @@ public class Camera {
* Called as preview frames are displayed. This callback is invoked
* on the event thread {@link #open(int)} was called from.
*
+ * <p>If using the {@link android.graphics.ImageFormat#YV12} format,
+ * refer to the equations in {@link Camera.Parameters#setPreviewFormat}
+ * for the arrangement of the pixel data in the preview callback
+ * buffers.
+ *
* @param data the contents of the preview frame in the format defined
* by {@link android.graphics.ImageFormat}, which can be queried
* with {@link android.hardware.Camera.Parameters#getPreviewFormat()}.
@@ -508,7 +513,9 @@ public class Camera {
mRawImageCallback = null;
mPostviewCallback = null;
mJpegCallback = null;
- mAutoFocusCallback = null;
+ synchronized (mAutoFocusCallbackLock) {
+ mAutoFocusCallback = null;
+ }
mAutoFocusMoveCallback = null;
}
@@ -611,12 +618,17 @@ public class Camera {
* the frame is discarded. Applications should add buffers back when they
* finish processing the data in them.
*
- * <p>The size of the buffer is determined by multiplying the preview
- * image width, height, and bytes per pixel. The width and height can be
- * read from {@link Camera.Parameters#getPreviewSize()}. Bytes per pixel
- * can be computed from
- * {@link android.graphics.ImageFormat#getBitsPerPixel(int)} / 8,
- * using the image format from {@link Camera.Parameters#getPreviewFormat()}.
+ * <p>For formats besides YV12, the size of the buffer is determined by
+ * multiplying the preview image width, height, and bytes per pixel. The
+ * width and height can be read from
+ * {@link Camera.Parameters#getPreviewSize()}. Bytes per pixel can be
+ * computed from {@link android.graphics.ImageFormat#getBitsPerPixel(int)} /
+ * 8, using the image format from
+ * {@link Camera.Parameters#getPreviewFormat()}.
+ *
+ * <p>If using the {@link android.graphics.ImageFormat#YV12} format, the
+ * size can be calculated using the equations listed in
+ * {@link Camera.Parameters#setPreviewFormat}.
*
* <p>This method is only necessary when
* {@link #setPreviewCallbackWithBuffer(PreviewCallback)} is used. When
@@ -626,8 +638,8 @@ public class Camera {
* hold the preview frame data, preview callback will return null and
* the buffer will be removed from the buffer queue.
*
- * @param callbackBuffer the buffer to add to the queue.
- * The size should be width * height * bits_per_pixel / 8.
+ * @param callbackBuffer the buffer to add to the queue. The size of the
+ * buffer must match the values described above.
* @see #setPreviewCallbackWithBuffer(PreviewCallback)
*/
public final void addCallbackBuffer(byte[] callbackBuffer)
@@ -748,14 +760,13 @@ public class Camera {
return;
case CAMERA_MSG_FOCUS:
- mFocusLock.lock();
- try {
- if (mAutoFocusCallback != null) {
- boolean success = msg.arg1 == 0 ? false : true;
- mAutoFocusCallback.onAutoFocus(success, mCamera);
- }
- } finally {
- mFocusLock.unlock();
+ AutoFocusCallback cb = null;
+ synchronized (mAutoFocusCallbackLock) {
+ cb = mAutoFocusCallback;
+ }
+ if (cb != null) {
+ boolean success = msg.arg1 == 0 ? false : true;
+ cb.onAutoFocus(success, mCamera);
}
return;
@@ -880,13 +891,10 @@ public class Camera {
*/
public final void autoFocus(AutoFocusCallback cb)
{
- mFocusLock.lock();
- try {
+ synchronized (mAutoFocusCallbackLock) {
mAutoFocusCallback = cb;
- native_autoFocus();
- } finally {
- mFocusLock.unlock();
}
+ native_autoFocus();
}
private native final void native_autoFocus();
@@ -900,14 +908,26 @@ public class Camera {
*/
public final void cancelAutoFocus()
{
- mFocusLock.lock();
- try {
+ synchronized (mAutoFocusCallbackLock) {
mAutoFocusCallback = null;
- native_cancelAutoFocus();
- removePendingAFCompletionMessages();
- } finally {
- mFocusLock.unlock();
}
+ native_cancelAutoFocus();
+ // CAMERA_MSG_FOCUS should be removed here because the following
+ // scenario can happen:
+ // - An application uses the same thread for autoFocus, cancelAutoFocus
+ // and looper thread.
+ // - The application calls autoFocus.
+ // - HAL sends CAMERA_MSG_FOCUS, which enters the looper message queue.
+ // Before event handler's handleMessage() is invoked, the application
+ // calls cancelAutoFocus and autoFocus.
+ // - The application gets the old CAMERA_MSG_FOCUS and thinks autofocus
+ // has been completed. But in fact it is not.
+ //
+ // As documented in the beginning of the file, apps should not use
+ // multiple threads to call autoFocus and cancelAutoFocus at the same
+ // time. It is HAL's responsibility not to send a CAMERA_MSG_FOCUS
+ // message after native_cancelAutoFocus is called.
+ mEventHandler.removeMessages(CAMERA_MSG_FOCUS);
}
private native final void native_cancelAutoFocus();
@@ -2289,12 +2309,44 @@ public class Camera {
* {@link android.graphics.ImageFormat#NV21}, which
* uses the NV21 encoding format.</p>
*
- * @param pixel_format the desired preview picture format, defined
- * by one of the {@link android.graphics.ImageFormat} constants.
- * (E.g., <var>ImageFormat.NV21</var> (default),
- * <var>ImageFormat.RGB_565</var>, or
- * <var>ImageFormat.JPEG</var>)
+ * <p>Use {@link Parameters#getSupportedPreviewFormats} to get a list of
+ * the available preview formats.
+ *
+ * <p>It is strongly recommended that either
+ * {@link android.graphics.ImageFormat#NV21} or
+ * {@link android.graphics.ImageFormat#YV12} is used, since
+ * they are supported by all camera devices.</p>
+ *
+ * <p>For YV12, the image buffer that is received is not necessarily
+ * tightly packed, as there may be padding at the end of each row of
+ * pixel data, as described in
+ * {@link android.graphics.ImageFormat#YV12}. For camera callback data,
+ * it can be assumed that the stride of the Y and UV data is the
+ * smallest possible that meets the alignment requirements. That is, if
+ * the preview size is <var>width x height</var>, then the following
+ * equations describe the buffer index for the beginning of row
+ * <var>y</var> for the Y plane and row <var>c</var> for the U and V
+ * planes:
+ *
+ * {@code
+ * <pre>
+ * yStride = (int) ceil(width / 16.0) * 16;
+ * uvStride = (int) ceil( (yStride / 2) / 16.0) * 16;
+ * ySize = yStride * height;
+ * uvSize = uvStride * height / 2;
+ * yRowIndex = yStride * y;
+ * uRowIndex = ySize + uvSize + uvStride * c;
+ * vRowIndex = ySize + uvStride * c;
+ * size = ySize + uvSize * 2;</pre>
+ * }
+ *
+ * @param pixel_format the desired preview picture format, defined by
+ * one of the {@link android.graphics.ImageFormat} constants. (E.g.,
+ * <var>ImageFormat.NV21</var> (default), or
+ * <var>ImageFormat.YV12</var>)
+ *
* @see android.graphics.ImageFormat
+ * @see android.hardware.Camera.Parameters#getSupportedPreviewFormats
*/
public void setPreviewFormat(int pixel_format) {
String s = cameraFormatForPixelFormat(pixel_format);
@@ -2312,6 +2364,7 @@ public class Camera {
*
* @return the preview format.
* @see android.graphics.ImageFormat
+ * @see #setPreviewFormat
*/
public int getPreviewFormat() {
return pixelFormatForCameraFormat(get(KEY_PREVIEW_FORMAT));
@@ -2325,6 +2378,7 @@ public class Camera {
* @return a list of supported preview formats. This method will always
* return a list with at least one element.
* @see android.graphics.ImageFormat
+ * @see #setPreviewFormat
*/
public List<Integer> getSupportedPreviewFormats() {
String str = get(KEY_PREVIEW_FORMAT + SUPPORTED_VALUES_SUFFIX);
@@ -3596,13 +3650,4 @@ public class Camera {
return false;
}
};
-
- /*
- * At any time, there should be at most one pending auto focus completion
- * message, but we simply remove all pending AF completion messages in
- * the looper's queue.
- */
- private void removePendingAFCompletionMessages() {
- mEventHandler.removeMessages(CAMERA_MSG_FOCUS);
- }
}
diff --git a/core/java/android/net/INetworkStatsService.aidl b/core/java/android/net/INetworkStatsService.aidl
index 08d4c6c..b7b8731 100644
--- a/core/java/android/net/INetworkStatsService.aidl
+++ b/core/java/android/net/INetworkStatsService.aidl
@@ -42,5 +42,7 @@ interface INetworkStatsService {
void setUidForeground(int uid, boolean uidForeground);
/** Force update of statistics. */
void forceUpdate();
+ /** Advise persistance threshold; may be overridden internally. */
+ void advisePersistThreshold(long thresholdBytes);
}
diff --git a/core/java/android/net/NetworkIdentity.java b/core/java/android/net/NetworkIdentity.java
index 4ac5e76..3c67bf9 100644
--- a/core/java/android/net/NetworkIdentity.java
+++ b/core/java/android/net/NetworkIdentity.java
@@ -158,9 +158,14 @@ public class NetworkIdentity {
}
} else if (type == TYPE_WIFI) {
- final WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
- final WifiInfo info = wifi.getConnectionInfo();
- networkId = info != null ? info.getSSID() : null;
+ if (state.networkId != null) {
+ networkId = state.networkId;
+ } else {
+ final WifiManager wifi = (WifiManager) context.getSystemService(
+ Context.WIFI_SERVICE);
+ final WifiInfo info = wifi.getConnectionInfo();
+ networkId = info != null ? info.getSSID() : null;
+ }
}
return new NetworkIdentity(type, subType, subscriberId, networkId, roaming);
diff --git a/core/java/android/net/NetworkState.java b/core/java/android/net/NetworkState.java
index 2fc69ad..fbe1f82 100644
--- a/core/java/android/net/NetworkState.java
+++ b/core/java/android/net/NetworkState.java
@@ -31,18 +31,20 @@ public class NetworkState implements Parcelable {
public final LinkCapabilities linkCapabilities;
/** Currently only used by testing. */
public final String subscriberId;
+ public final String networkId;
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
LinkCapabilities linkCapabilities) {
- this(networkInfo, linkProperties, linkCapabilities, null);
+ this(networkInfo, linkProperties, linkCapabilities, null, null);
}
public NetworkState(NetworkInfo networkInfo, LinkProperties linkProperties,
- LinkCapabilities linkCapabilities, String subscriberId) {
+ LinkCapabilities linkCapabilities, String subscriberId, String networkId) {
this.networkInfo = networkInfo;
this.linkProperties = linkProperties;
this.linkCapabilities = linkCapabilities;
this.subscriberId = subscriberId;
+ this.networkId = networkId;
}
public NetworkState(Parcel in) {
@@ -50,6 +52,7 @@ public class NetworkState implements Parcelable {
linkProperties = in.readParcelable(null);
linkCapabilities = in.readParcelable(null);
subscriberId = in.readString();
+ networkId = in.readString();
}
@Override
@@ -63,6 +66,7 @@ public class NetworkState implements Parcelable {
out.writeParcelable(linkProperties, flags);
out.writeParcelable(linkCapabilities, flags);
out.writeString(subscriberId);
+ out.writeString(networkId);
}
public static final Creator<NetworkState> CREATOR = new Creator<NetworkState>() {
diff --git a/core/java/android/os/ConditionVariable.java b/core/java/android/os/ConditionVariable.java
index 95a9259..07b221c 100644
--- a/core/java/android/os/ConditionVariable.java
+++ b/core/java/android/os/ConditionVariable.java
@@ -26,7 +26,7 @@ package android.os;
* block() will not block, and instead return immediately.
*
* <p>
- * This class uses itself is at the object to wait on, so if you wait()
+ * This class uses itself as the object to wait on, so if you wait()
* or notify() on a ConditionVariable, the results are undefined.
*/
public class ConditionVariable
diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java
index d61b3b4..daf1f59 100644
--- a/core/java/android/os/HandlerThread.java
+++ b/core/java/android/os/HandlerThread.java
@@ -42,7 +42,7 @@ public class HandlerThread extends Thread {
}
/**
- * Call back method that can be explicitly over ridden if needed to execute some
+ * Call back method that can be explicitly overridden if needed to execute some
* setup before Looper loops.
*/
protected void onLooperPrepared() {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 6ecc640..e7ea355 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -238,7 +238,8 @@ interface INetworkManagementService
* Return global network statistics summarized at an interface level,
* without any UID-level granularity.
*/
- NetworkStats getNetworkStatsSummary();
+ NetworkStats getNetworkStatsSummaryDev();
+ NetworkStats getNetworkStatsSummaryXt();
/**
* Return detailed network statistics with UID-level granularity,
diff --git a/core/java/android/os/Message.java b/core/java/android/os/Message.java
index 4aa7fe2..0abc149 100644
--- a/core/java/android/os/Message.java
+++ b/core/java/android/os/Message.java
@@ -97,8 +97,8 @@ public final class Message implements Parcelable {
private static Message sPool;
private static int sPoolSize = 0;
- private static final int MAX_POOL_SIZE = 10;
-
+ private static final int MAX_POOL_SIZE = 50;
+
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 2a45506..05acd63 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -36,6 +36,7 @@ public final class Trace {
public static final long TRACE_TAG_WEBVIEW = 1L << 4;
public static final long TRACE_TAG_WINDOW_MANAGER = 1L << 5;
public static final long TRACE_TAG_ACTIVITY_MANAGER = 1L << 6;
+ public static final long TRACE_TAG_SYNC_MANAGER = 1L << 7;
private static final long sEnabledTags = nativeGetEnabledTags();
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 6d14dfc..7824724 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -25,6 +25,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
+import android.provider.ContactsContract.CommonDataKinds.Callable;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.DataUsageFeedback;
import android.text.TextUtils;
@@ -312,10 +313,12 @@ public class CallLog {
null);
} else {
final String phoneNumber = ci.phoneNumber != null ? ci.phoneNumber : number;
- cursor = resolver.query(Phone.CONTENT_URI,
+ cursor = resolver.query(
+ Uri.withAppendedPath(Callable.CONTENT_FILTER_URI,
+ Uri.encode(phoneNumber)),
new String[] { Phone._ID },
- Phone.CONTACT_ID + " =? AND " + Phone.NUMBER + " =?",
- new String[] { String.valueOf(ci.person_id), phoneNumber},
+ Phone.CONTACT_ID + " =?",
+ new String[] { String.valueOf(ci.person_id) },
null);
}
diff --git a/core/java/android/provider/SocialContract.java b/core/java/android/provider/SocialContract.java
deleted file mode 100644
index ee271ba..0000000
--- a/core/java/android/provider/SocialContract.java
+++ /dev/null
@@ -1,187 +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
- */
-
-package android.provider;
-
-import android.content.res.Resources;
-import android.graphics.BitmapFactory;
-import android.net.Uri;
-import android.provider.ContactsContract.Contacts;
-import android.provider.ContactsContract.Data;
-
-/**
- * The contract between the social provider and applications. Contains
- * definitions for the supported URIs and columns.
- *
- * @hide
- */
-public class SocialContract {
- /** The authority for the social provider */
- public static final String AUTHORITY = "com.android.social";
-
- /** A content:// style uri to the authority for the contacts provider */
- public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
-
- private interface ActivitiesColumns {
- /**
- * The package name to use when creating {@link Resources} objects for
- * this data row. This value is only designed for use when building user
- * interfaces, and should not be used to infer the owner.
- * <p>
- * Type: TEXT
- */
- public static final String RES_PACKAGE = "res_package";
-
- /**
- * The mime-type of this social activity.
- * <p>
- * Type: TEXT
- */
- public static final String MIMETYPE = "mimetype";
-
- /**
- * Internal raw identifier for this social activity. This field is
- * analogous to the <code>atom:id</code> element defined in RFC 4287.
- * <p>
- * Type: TEXT
- */
- public static final String RAW_ID = "raw_id";
-
- /**
- * Reference to another {@link Activities#RAW_ID} that this social activity
- * is replying to. This field is analogous to the
- * <code>thr:in-reply-to</code> element defined in RFC 4685.
- * <p>
- * Type: TEXT
- */
- public static final String IN_REPLY_TO = "in_reply_to";
-
- /**
- * Reference to the {@link android.provider.ContactsContract.Contacts#_ID} that authored
- * this social activity. This field is analogous to the <code>atom:author</code>
- * element defined in RFC 4287.
- * <p>
- * Type: INTEGER
- */
- public static final String AUTHOR_CONTACT_ID = "author_contact_id";
-
- /**
- * Optional reference to the {@link android.provider.ContactsContract.Contacts#_ID} this
- * social activity is targeted towards. If more than one direct target, this field may
- * be left undefined. This field is analogous to the
- * <code>activity:target</code> element defined in the Atom Activity
- * Extensions Internet-Draft.
- * <p>
- * Type: INTEGER
- */
- public static final String TARGET_CONTACT_ID = "target_contact_id";
-
- /**
- * Timestamp when this social activity was published, in a
- * {@link System#currentTimeMillis()} time base. This field is analogous
- * to the <code>atom:published</code> element defined in RFC 4287.
- * <p>
- * Type: INTEGER
- */
- public static final String PUBLISHED = "published";
-
- /**
- * Timestamp when the original social activity in a thread was
- * published. For activities that have an in-reply-to field specified, the
- * content provider will automatically populate this field with the
- * timestamp of the original activity.
- * <p>
- * This field is useful for sorting order of activities that keeps together all
- * messages in each thread.
- * <p>
- * Type: INTEGER
- */
- public static final String THREAD_PUBLISHED = "thread_published";
-
- /**
- * Title of this social activity. This field is analogous to the
- * <code>atom:title</code> element defined in RFC 4287.
- * <p>
- * Type: TEXT
- */
- public static final String TITLE = "title";
-
- /**
- * Summary of this social activity. This field is analogous to the
- * <code>atom:summary</code> element defined in RFC 4287.
- * <p>
- * Type: TEXT
- */
- public static final String SUMMARY = "summary";
-
- /**
- * A URI associated this social activity. This field is analogous to the
- * <code>atom:link rel="alternate"</code> element defined in RFC 4287.
- * <p>
- * Type: TEXT
- */
- public static final String LINK = "link";
-
- /**
- * Optional thumbnail specific to this social activity. This is the raw
- * bytes of an image that could be inflated using {@link BitmapFactory}.
- * <p>
- * Type: BLOB
- */
- public static final String THUMBNAIL = "thumbnail";
- }
-
- public static final class Activities implements BaseColumns, ActivitiesColumns {
- /**
- * This utility class cannot be instantiated
- */
- private Activities() {
- }
-
- /**
- * The content:// style URI for this table
- */
- public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "activities");
-
- /**
- * The content:// URI for this table filtered to the set of social activities
- * authored by a specific {@link android.provider.ContactsContract.Contacts#_ID}.
- */
- public static final Uri CONTENT_AUTHORED_BY_URI =
- Uri.withAppendedPath(CONTENT_URI, "authored_by");
-
- /**
- * The {@link Uri} for the latest social activity performed by any
- * raw contact aggregated under the specified {@link Contacts#_ID}. Will
- * also join with most-present {@link Presence} for this aggregate.
- */
- public static final Uri CONTENT_CONTACT_STATUS_URI =
- Uri.withAppendedPath(AUTHORITY_URI, "contact_status");
-
- /**
- * The MIME type of {@link #CONTENT_URI} providing a directory of social
- * activities.
- */
- public static final String CONTENT_TYPE = "vnd.android.cursor.dir/activity";
-
- /**
- * The MIME type of a {@link #CONTENT_URI} subdirectory of a single
- * social activity.
- */
- public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/activity";
- }
-
-}
diff --git a/core/java/android/service/textservice/SpellCheckerService.java b/core/java/android/service/textservice/SpellCheckerService.java
index c579e6e..77b22ed 100644
--- a/core/java/android/service/textservice/SpellCheckerService.java
+++ b/core/java/android/service/textservice/SpellCheckerService.java
@@ -397,14 +397,6 @@ public abstract class SpellCheckerService extends Service {
}
wordStart = wordIterator.getBeginning(wordEnd);
}
- if (originalText.length() >= SpellChecker.WORD_ITERATOR_INTERVAL
- && wordItems.size() >= 2) {
- if (DBG) {
- Log.w(TAG, "Remove possibly divided word: "
- + wordItems.get(0).mTextInfo.getText());
- }
- wordItems.remove(0);
- }
return new SentenceTextInfoParams(originalTextInfo, wordItems);
}
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index 09c9438..0f30d25 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -308,6 +308,7 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
resizeFor(mText.length + nbNewChars - mGapLength);
}
+ final boolean textIsRemoved = replacementLength == 0;
// The removal pass needs to be done before the gap is updated in order to broadcast the
// correct previous positions to the correct intersecting SpanWatchers
if (replacedLength > 0) { // no need for span fixup on pure insertion
@@ -319,12 +320,15 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
while (i < mSpanCount) {
if ((mSpanFlags[i] & Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) ==
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE &&
- mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength &&
- mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength) {
+ mSpanStarts[i] >= start && mSpanStarts[i] < mGapStart + mGapLength &&
+ mSpanEnds[i] >= start && mSpanEnds[i] < mGapStart + mGapLength &&
+ // This condition indicates that the span would become empty
+ (textIsRemoved || mSpanStarts[i] > start || mSpanEnds[i] < mGapStart)) {
removeSpan(i);
- } else {
- i++;
+ continue; // do not increment i, spans will be shifted left in the array
}
+
+ i++;
}
}
@@ -338,7 +342,6 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
if (replacedLength > 0) { // no need for span fixup on pure insertion
final boolean atEnd = (mGapStart + mGapLength == mText.length);
- final boolean textIsRemoved = replacementLength == 0;
for (int i = 0; i < mSpanCount; i++) {
final int startFlag = (mSpanFlags[i] & START_MASK) >> START_SHIFT;
@@ -390,9 +393,9 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
return mGapStart + mGapLength;
}
} else { // MARK
- // MARKs should be moved to the start, with the exception of a mark located at the
- // end of the range (which will be < mGapStart + mGapLength since mGapLength > 0)
- // which should stay 'unchanged' at the end of the replaced text.
+ // MARKs should be moved to the start, with the exception of a mark located at
+ // the end of the range (which will be < mGapStart + mGapLength since mGapLength
+ // is > 0, which should stay 'unchanged' at the end of the replaced text.
if (textIsRemoved || offset < mGapStart - nbNewChars) {
return start;
} else {
diff --git a/core/java/android/text/TextDirectionHeuristics.java b/core/java/android/text/TextDirectionHeuristics.java
index bbaa173..be2840b 100644
--- a/core/java/android/text/TextDirectionHeuristics.java
+++ b/core/java/android/text/TextDirectionHeuristics.java
@@ -22,7 +22,6 @@ import android.view.View;
/**
* Some objects that implement TextDirectionHeuristic.
- *
* @hide
*/
public class TextDirectionHeuristics {
diff --git a/core/java/android/util/LocaleUtil.java b/core/java/android/util/LocaleUtil.java
index 60526e1..93f5cd3 100644
--- a/core/java/android/util/LocaleUtil.java
+++ b/core/java/android/util/LocaleUtil.java
@@ -24,6 +24,7 @@ import libcore.icu.ICU;
/**
* Various utilities for Locales
*
+ * @hide
*/
public class LocaleUtil {
@@ -40,7 +41,8 @@ public class LocaleUtil {
* {@link View#LAYOUT_DIRECTION_LTR} or
* {@link View#LAYOUT_DIRECTION_RTL}.
*
- * Be careful: this code will need to be updated when vertical scripts will be supported
+ * Warning: this code does not support vertical scripts.
+ * @hide
*/
public static int getLayoutDirectionFromLocale(Locale locale) {
if (locale != null && !locale.equals(Locale.ROOT)) {
@@ -66,8 +68,7 @@ public class LocaleUtil {
* {@link View#LAYOUT_DIRECTION_LTR} or
* {@link View#LAYOUT_DIRECTION_RTL}.
*
- * Be careful: this code will need to be updated when vertical scripts will be supported
- *
+ * Warning: this code does not support vertical scripts.
* @hide
*/
private static int getLayoutDirectionFromFirstChar(Locale locale) {
diff --git a/core/java/android/util/MathUtils.java b/core/java/android/util/MathUtils.java
index b35dd1e..13a692e 100644
--- a/core/java/android/util/MathUtils.java
+++ b/core/java/android/util/MathUtils.java
@@ -39,6 +39,10 @@ public final class MathUtils {
return amount < low ? low : (amount > high ? high : amount);
}
+ public static long constrain(long amount, long low, long high) {
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+
public static float constrain(float amount, float low, float high) {
return amount < low ? low : (amount > high ? high : amount);
}
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index bda8016..c947312 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -391,6 +391,15 @@ public class Display {
}
/**
+ * If the display is mirrored to an external HDMI display, returns the
+ * rotation of that display relative to its natural orientation.
+ * @hide
+ */
+ public int getExternalRotation() {
+ return Surface.ROTATION_0;
+ }
+
+ /**
* Gets display metrics based on an explicit assumed display size.
* @hide
*/
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index fba73fbd..3dab174 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -30,7 +30,7 @@ import android.graphics.Matrix;
public abstract class DisplayList {
/**
* Flag used when calling
- * {@link HardwareCanvas#drawDisplayList(DisplayList, int, int, android.graphics.Rect, int)}.
+ * {@link HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)}
* When this flag is set, draw operations lying outside of the bounds of the
* display list will be culled early. It is recommeneded to always set this
* flag.
@@ -42,21 +42,21 @@ public abstract class DisplayList {
/**
* Indicates that the display list is done drawing.
*
- * @see HardwareCanvas#drawDisplayList(DisplayList, int, int, android.graphics.Rect, int)
+ * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
*/
public static final int STATUS_DONE = 0x0;
/**
* Indicates that the display list needs another drawing pass.
*
- * @see HardwareCanvas#drawDisplayList(DisplayList, int, int, android.graphics.Rect, int)
+ * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
*/
public static final int STATUS_DRAW = 0x1;
/**
* Indicates that the display list needs to re-execute its GL functors.
*
- * @see HardwareCanvas#drawDisplayList(DisplayList, int, int, android.graphics.Rect, int)
+ * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
* @see HardwareCanvas#callDrawGLFunction(int)
*/
public static final int STATUS_INVOKE = 0x2;
diff --git a/core/java/android/view/FocusFinder.java b/core/java/android/view/FocusFinder.java
index 98375ae..6bf1888 100644
--- a/core/java/android/view/FocusFinder.java
+++ b/core/java/android/view/FocusFinder.java
@@ -62,7 +62,7 @@ public class FocusFinder {
* @return The next focusable view, or null if none exists.
*/
public final View findNextFocus(ViewGroup root, View focused, int direction) {
- return findNextFocus(root, focused, mFocusedRect, direction);
+ return findNextFocus(root, focused, null, direction);
}
/**
@@ -122,34 +122,40 @@ public class FocusFinder {
int direction, ArrayList<View> focusables) {
final int directionMasked = (direction & ~View.FOCUS_ACCESSIBILITY);
if (focused != null) {
+ if (focusedRect == null) {
+ focusedRect = mFocusedRect;
+ }
// fill in interesting rect from focused
focused.getFocusedRect(focusedRect);
root.offsetDescendantRectToMyCoords(focused, focusedRect);
} else {
- // make up a rect at top left or bottom right of root
- switch (directionMasked) {
- case View.FOCUS_RIGHT:
- case View.FOCUS_DOWN:
- setFocusTopLeft(root, focusedRect);
- break;
- case View.FOCUS_FORWARD:
- if (root.isLayoutRtl()) {
- setFocusBottomRight(root, focusedRect);
- } else {
- setFocusTopLeft(root, focusedRect);
- }
- break;
-
- case View.FOCUS_LEFT:
- case View.FOCUS_UP:
- setFocusBottomRight(root, focusedRect);
- break;
- case View.FOCUS_BACKWARD:
- if (root.isLayoutRtl()) {
+ if (focusedRect == null) {
+ focusedRect = mFocusedRect;
+ // make up a rect at top left or bottom right of root
+ switch (directionMasked) {
+ case View.FOCUS_RIGHT:
+ case View.FOCUS_DOWN:
setFocusTopLeft(root, focusedRect);
- } else {
+ break;
+ case View.FOCUS_FORWARD:
+ if (root.isLayoutRtl()) {
+ setFocusBottomRight(root, focusedRect);
+ } else {
+ setFocusTopLeft(root, focusedRect);
+ }
+ break;
+
+ case View.FOCUS_LEFT:
+ case View.FOCUS_UP:
setFocusBottomRight(root, focusedRect);
- break;
+ break;
+ case View.FOCUS_BACKWARD:
+ if (root.isLayoutRtl()) {
+ setFocusTopLeft(root, focusedRect);
+ } else {
+ setFocusBottomRight(root, focusedRect);
+ break;
+ }
}
}
}
diff --git a/core/java/android/view/Gravity.java b/core/java/android/view/Gravity.java
index f031fe7..4547aa6 100644
--- a/core/java/android/view/Gravity.java
+++ b/core/java/android/view/Gravity.java
@@ -155,6 +155,7 @@ public class Gravity
*
* @see {@link View#LAYOUT_DIRECTION_LTR}
* @see {@link View#LAYOUT_DIRECTION_RTL}
+ * @hide
*/
public static void apply(int gravity, int w, int h, Rect container,
Rect outRect, int layoutDirection) {
@@ -292,6 +293,7 @@ public class Gravity
*
* @see {@link View#LAYOUT_DIRECTION_LTR}
* @see {@link View#LAYOUT_DIRECTION_RTL}
+ * @hide
*/
public static void apply(int gravity, int w, int h, Rect container,
int xAdj, int yAdj, Rect outRect, int layoutDirection) {
@@ -372,6 +374,7 @@ public class Gravity
*
* @see {@link View#LAYOUT_DIRECTION_LTR}
* @see {@link View#LAYOUT_DIRECTION_RTL}
+ * @hide
*/
public static void applyDisplay(int gravity, Rect display, Rect inoutObj, int layoutDirection) {
int absGravity = getAbsoluteGravity(gravity, layoutDirection);
@@ -408,6 +411,7 @@ public class Gravity
* @param gravity The gravity to convert to absolute (horizontal) values.
* @param layoutDirection The layout direction.
* @return gravity converted to absolute (horizontal) values.
+ * @hide
*/
public static int getAbsoluteGravity(int gravity, int layoutDirection) {
int result = gravity;
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index c0771c5..e25e2ef 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -152,7 +152,7 @@ public abstract class HardwareRenderer {
/**
* Number of frames to profile.
*/
- private static final int PROFILE_MAX_FRAMES = 64;
+ private static final int PROFILE_MAX_FRAMES = 128;
/**
* Number of floats per profiled frame.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 2f67481..5299d58 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -340,10 +340,9 @@ import java.util.concurrent.CopyOnWriteArrayList;
* Padding can be used to offset the content of the view by a specific amount of
* pixels. For instance, a left padding of 2 will push the view's content by
* 2 pixels to the right of the left edge. Padding can be set using the
- * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
- * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
- * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
- * {@link #getPaddingEnd()}.
+ * {@link #setPadding(int, int, int, int)} method and queried by calling
+ * {@link #getPaddingLeft()}, {@link #getPaddingTop()}, {@link #getPaddingRight()},
+ * {@link #getPaddingBottom()}.
* </p>
*
* <p>
@@ -537,9 +536,32 @@ import java.util.concurrent.CopyOnWriteArrayList;
* themselves rather than by putting them in a separate structure.
* </p>
*
+ * <a name="Properties"></a>
+ * <h3>Properties</h3>
+ * <p>
+ * The View class exposes an {@link #ALPHA} property, as well as several transform-related
+ * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
+ * available both in the {@link Property} form as well as in similarly-named setter/getter
+ * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
+ * be used to set persistent state associated with these rendering-related properties on the view.
+ * The properties and methods can also be used in conjunction with
+ * {@link android.animation.Animator Animator}-based animations, described more in the
+ * <a href="#Animation">Animation</a> section.
+ * </p>
+ *
* <a name="Animation"></a>
* <h3>Animation</h3>
* <p>
+ * Starting with Android 3.0, the preferred way of animating views is to use the
+ * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
+ * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
+ * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
+ * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
+ * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
+ * makes animating these View properties particularly easy and efficient.
+ * </p>
+ * <p>
+ * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
* You can attach an {@link Animation} object to a view using
* {@link #setAnimation(Animation)} or
* {@link #startAnimation(Animation)}. The animation can alter the scale,
@@ -548,10 +570,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
* subtree rooted by that node. When an animation is started, the framework will
* take care of redrawing the appropriate views until the animation completes.
* </p>
- * <p>
- * Starting with Android 3.0, the preferred way of animating views is to use the
- * {@link android.animation} package APIs.
- * </p>
*
* <a name="Security"></a>
* <h3>Security</h3>
@@ -606,8 +624,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @attr ref android.R.styleable#View_paddingLeft
* @attr ref android.R.styleable#View_paddingRight
* @attr ref android.R.styleable#View_paddingTop
- * @attr ref android.R.styleable#View_paddingStart
- * @attr ref android.R.styleable#View_paddingEnd
* @attr ref android.R.styleable#View_saveEnabled
* @attr ref android.R.styleable#View_rotation
* @attr ref android.R.styleable#View_rotationX
@@ -629,7 +645,6 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
* @attr ref android.R.styleable#View_soundEffectsEnabled
* @attr ref android.R.styleable#View_tag
- * @attr ref android.R.styleable#View_textAlignment
* @attr ref android.R.styleable#View_transformPivotX
* @attr ref android.R.styleable#View_transformPivotY
* @attr ref android.R.styleable#View_translationX
@@ -1763,24 +1778,28 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Horizontal layout direction of this view is from Left to Right.
* Use with {@link #setLayoutDirection}.
+ * @hide
*/
public static final int LAYOUT_DIRECTION_LTR = 0;
/**
* Horizontal layout direction of this view is from Right to Left.
* Use with {@link #setLayoutDirection}.
+ * @hide
*/
public static final int LAYOUT_DIRECTION_RTL = 1;
/**
* Horizontal layout direction of this view is inherited from its parent.
* Use with {@link #setLayoutDirection}.
+ * @hide
*/
public static final int LAYOUT_DIRECTION_INHERIT = 2;
/**
* Horizontal layout direction of this view is from deduced from the default language
* script for the locale. Use with {@link #setLayoutDirection}.
+ * @hide
*/
public static final int LAYOUT_DIRECTION_LOCALE = 3;
@@ -1845,6 +1864,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Text direction is inherited thru {@link ViewGroup}
+ * @hide
*/
public static final int TEXT_DIRECTION_INHERIT = 0;
@@ -1852,6 +1872,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Text direction is using "first strong algorithm". The first strong directional character
* determines the paragraph direction. If there is no strong directional character, the
* paragraph direction is the view's resolved layout direction.
+ * @hide
*/
public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
@@ -1859,26 +1880,31 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
* any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
* If there are neither, the paragraph direction is the view's resolved layout direction.
+ * @hide
*/
public static final int TEXT_DIRECTION_ANY_RTL = 2;
/**
* Text direction is forced to LTR.
+ * @hide
*/
public static final int TEXT_DIRECTION_LTR = 3;
/**
* Text direction is forced to RTL.
+ * @hide
*/
public static final int TEXT_DIRECTION_RTL = 4;
/**
* Text direction is coming from the system Locale.
+ * @hide
*/
public static final int TEXT_DIRECTION_LOCALE = 5;
/**
* Default text direction is inherited
+ * @hide
*/
protected static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
@@ -1936,6 +1962,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/*
* Default text alignment. The text alignment of this View is inherited from its parent.
* Use with {@link #setTextAlignment(int)}
+ * @hide
*/
public static final int TEXT_ALIGNMENT_INHERIT = 0;
@@ -1944,6 +1971,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
*
* Use with {@link #setTextAlignment(int)}
+ * @hide
*/
public static final int TEXT_ALIGNMENT_GRAVITY = 1;
@@ -1951,6 +1979,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Align to the start of the paragraph, e.g. ALIGN_NORMAL.
*
* Use with {@link #setTextAlignment(int)}
+ * @hide
*/
public static final int TEXT_ALIGNMENT_TEXT_START = 2;
@@ -1958,6 +1987,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
*
* Use with {@link #setTextAlignment(int)}
+ * @hide
*/
public static final int TEXT_ALIGNMENT_TEXT_END = 3;
@@ -1965,6 +1995,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Center the paragraph, e.g. ALIGN_CENTER.
*
* Use with {@link #setTextAlignment(int)}
+ * @hide
*/
public static final int TEXT_ALIGNMENT_CENTER = 4;
@@ -1973,6 +2004,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* layoutDirection is LTR, and ALIGN_RIGHT otherwise.
*
* Use with {@link #setTextAlignment(int)}
+ * @hide
*/
public static final int TEXT_ALIGNMENT_VIEW_START = 5;
@@ -1981,11 +2013,13 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* layoutDirection is LTR, and ALIGN_LEFT otherwise.
*
* Use with {@link #setTextAlignment(int)}
+ * @hide
*/
public static final int TEXT_ALIGNMENT_VIEW_END = 6;
/**
* Default text alignment is inherited
+ * @hide
*/
protected static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
@@ -4681,10 +4715,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
if (getContentDescription() != null) {
- info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY);
- info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY);
- info.setGranularities(AccessibilityNodeInfo.GRANULARITY_CHARACTER
- | AccessibilityNodeInfo.GRANULARITY_WORD);
+ info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
+ info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
+ info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
+ | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD);
}
}
@@ -5352,7 +5386,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #LAYOUT_DIRECTION_RTL},
* {@link #LAYOUT_DIRECTION_INHERIT} or
* {@link #LAYOUT_DIRECTION_LOCALE}.
+ *
* @attr ref android.R.styleable#View_layoutDirection
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
@@ -5374,6 +5410,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #LAYOUT_DIRECTION_LOCALE}.
*
* @attr ref android.R.styleable#View_layoutDirection
+ * @hide
*/
@RemotableViewMethod
public void setLayoutDirection(int layoutDirection) {
@@ -5393,6 +5430,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
* {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "layout", mapping = {
@ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
@@ -5412,6 +5450,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* layout attribute and/or the inherited value from the parent
*
* @return true if the layout is right-to-left.
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public boolean isLayoutRtl() {
@@ -6414,12 +6453,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK: {
if (isClickable()) {
- performClick();
+ return performClick();
}
} break;
case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
if (isLongClickable()) {
- performLongClick();
+ return performLongClick();
}
} break;
case AccessibilityNodeInfo.ACTION_FOCUS: {
@@ -9148,7 +9187,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
public final boolean getLocalVisibleRect(Rect r) {
- Point offset = new Point();
+ final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
if (getGlobalVisibleRect(r, offset)) {
r.offset(-offset.x, -offset.y); // make r local
return true;
@@ -10878,6 +10917,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
* that the parent directionality can and will be resolved before its children.
* Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
+ * @hide
*/
public void resolveLayoutDirection() {
// Clear any previous layout direction resolution
@@ -10922,12 +10962,14 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Called when layout direction has been resolved.
*
* The default implementation does nothing.
+ * @hide
*/
public void onResolvedLayoutDirectionChanged() {
}
/**
* Resolve padding depending on layout direction.
+ * @hide
*/
public void resolvePadding() {
// If the user specified the absolute padding (either with android:padding or
@@ -10987,6 +11029,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @see {@link #LAYOUT_DIRECTION_LTR}
* @see {@link #LAYOUT_DIRECTION_RTL}
+ * @hide
*/
public void onPaddingChanged(int layoutDirection) {
}
@@ -10995,6 +11038,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Check if layout direction resolution can be done.
*
* @return true if layout direction resolution can be done otherwise return false.
+ * @hide
*/
public boolean canResolveLayoutDirection() {
switch (getLayoutDirection()) {
@@ -11008,6 +11052,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
* when reset is done.
+ * @hide
*/
public void resetResolvedLayoutDirection() {
// Reset the current resolved bits
@@ -11024,6 +11069,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* resolved layout direction, or to inform child views that inherit their layout direction.
*
* The default implementation does nothing.
+ * @hide
*/
public void onResolvedLayoutDirectionReset() {
}
@@ -11033,6 +11079,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*
* @param locale Locale to check
* @return true if the Locale uses an RTL script.
+ * @hide
*/
protected static boolean isLayoutDirectionRtl(Locale locale) {
return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
@@ -13337,6 +13384,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Return the layout direction of a given Drawable.
*
* @param who the Drawable to query
+ * @hide
*/
public int getResolvedLayoutDirection(Drawable who) {
return (who == mBackground) ? getResolvedLayoutDirection() : LAYOUT_DIRECTION_DEFAULT;
@@ -13772,19 +13820,13 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Sets the relative padding. The view may add on the space required to display
* the scrollbars, depending on the style and visibility of the scrollbars.
- * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
- * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
* from the values set in this call.
*
- * @attr ref android.R.styleable#View_padding
- * @attr ref android.R.styleable#View_paddingBottom
- * @attr ref android.R.styleable#View_paddingStart
- * @attr ref android.R.styleable#View_paddingEnd
- * @attr ref android.R.styleable#View_paddingTop
* @param start the start padding in pixels
* @param top the top padding in pixels
* @param end the end padding in pixels
* @param bottom the bottom padding in pixels
+ * @hide
*/
public void setPaddingRelative(int start, int top, int end, int bottom) {
mUserPaddingStart = start;
@@ -13838,6 +13880,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* required to display the scrollbars as well.
*
* @return the start padding in pixels
+ * @hide
*/
public int getPaddingStart() {
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
@@ -13861,6 +13904,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* required to display the scrollbars as well.
*
* @return the end padding in pixels
+ * @hide
*/
public int getPaddingEnd() {
return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
@@ -13869,11 +13913,10 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Return if the padding as been set thru relative values
- * {@link #setPaddingRelative(int, int, int, int)} or thru
- * @attr ref android.R.styleable#View_paddingStart or
- * @attr ref android.R.styleable#View_paddingEnd
+ * {@link #setPaddingRelative(int, int, int, int)}
*
* @return true if the padding is relative or false if it is not.
+ * @hide
*/
public boolean isPaddingRelative() {
return mUserPaddingRelative;
@@ -15193,6 +15236,18 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
}
}
+ /** @hide */
+ public void setDisabledSystemUiVisibility(int flags) {
+ if (mAttachInfo != null) {
+ if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
+ mAttachInfo.mDisabledSystemUiVisibility = flags;
+ if (mParent != null) {
+ mParent.recomputeViewAttributes(this);
+ }
+ }
+ }
+ }
+
/**
* Creates an image that the system displays during the drag and drop
* operation. This is called a &quot;drag shadow&quot;. The default implementation
@@ -15717,6 +15772,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_DIRECTION_LTR},
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
@@ -15741,6 +15797,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_DIRECTION_LTR},
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
+ * @hide
*/
public void setTextDirection(int textDirection) {
if (getTextDirection() != textDirection) {
@@ -15770,6 +15827,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_DIRECTION_LTR},
* {@link #TEXT_DIRECTION_RTL},
* {@link #TEXT_DIRECTION_LOCALE}
+ * @hide
*/
public int getResolvedTextDirection() {
// The text direction will be resolved only if needed
@@ -15782,6 +15840,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
* resolution is done.
+ * @hide
*/
public void resolveTextDirection() {
// Reset any previous text direction resolution
@@ -15842,6 +15901,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* resolution should override this method.
*
* The default implementation does nothing.
+ * @hide
*/
public void onResolvedTextDirectionChanged() {
}
@@ -15850,6 +15910,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Check if text direction resolution can be done.
*
* @return true if text direction resolution can be done otherwise return false.
+ * @hide
*/
public boolean canResolveTextDirection() {
switch (getTextDirection()) {
@@ -15864,6 +15925,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Reset resolved text direction. Text direction can be resolved with a call to
* getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
* reset is done.
+ * @hide
*/
public void resetResolvedTextDirection() {
mPrivateFlags2 &= ~(TEXT_DIRECTION_RESOLVED | TEXT_DIRECTION_RESOLVED_MASK);
@@ -15874,6 +15936,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Called when text direction is reset. Subclasses that care about text direction reset should
* override this method and do a reset of the text direction of their children. The default
* implementation does nothing.
+ * @hide
*/
public void onResolvedTextDirectionReset() {
}
@@ -15891,6 +15954,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_ALIGNMENT_TEXT_END},
* {@link #TEXT_ALIGNMENT_VIEW_START},
* {@link #TEXT_ALIGNMENT_VIEW_END}
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
@@ -15919,6 +15983,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_ALIGNMENT_VIEW_END}
*
* @attr ref android.R.styleable#View_textAlignment
+ * @hide
*/
public void setTextAlignment(int textAlignment) {
if (textAlignment != getTextAlignment()) {
@@ -15948,6 +16013,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* {@link #TEXT_ALIGNMENT_TEXT_END},
* {@link #TEXT_ALIGNMENT_VIEW_START},
* {@link #TEXT_ALIGNMENT_VIEW_END}
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "text", mapping = {
@ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
@@ -15969,6 +16035,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
/**
* Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
* resolution is done.
+ * @hide
*/
public void resolveTextAlignment() {
// Reset any previous text alignment resolution
@@ -16033,6 +16100,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Check if text alignment resolution can be done.
*
* @return true if text alignment resolution can be done otherwise return false.
+ * @hide
*/
public boolean canResolveTextAlignment() {
switch (getTextAlignment()) {
@@ -16048,6 +16116,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* resolution should override this method.
*
* The default implementation does nothing.
+ * @hide
*/
public void onResolvedTextAlignmentChanged() {
}
@@ -16056,6 +16125,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Reset resolved text alignment. Text alignment can be resolved with a call to
* getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
* reset is done.
+ * @hide
*/
public void resetResolvedTextAlignment() {
// Reset any previous text alignment resolution
@@ -16067,6 +16137,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
* Called when text alignment is reset. Subclasses that care about text alignment reset should
* override this method and do a reset of the text alignment of their children. The default
* implementation does nothing.
+ * @hide
*/
public void onResolvedTextAlignmentReset() {
}
@@ -16762,6 +16833,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
boolean mUse32BitDrawingCache;
/**
+ * Describes the parts of the window that are currently completely
+ * obscured by system UI elements.
+ */
+ final Rect mSystemInsets = new Rect();
+
+ /**
* For windows that are full-screen but using insets to layout inside
* of the screen decorations, these are the current insets for the
* content of the window.
@@ -16848,6 +16925,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
int mSystemUiVisibility;
/**
+ * Hack to force certain system UI visibility flags to be cleared.
+ */
+ int mDisabledSystemUiVisibility;
+
+ /**
* True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
* attached.
*/
@@ -16942,6 +17024,11 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
final boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
/**
+ * Point used to compute visible regions.
+ */
+ final Point mPoint = new Point();
+
+ /**
* Creates a new set of attachment information with the specified
* events handler and thread.
*
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 89ec51f..29613d5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -348,6 +348,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* This constant is a {@link #setLayoutMode(int) layoutMode}.
* Clip bounds are the raw values of {@link #getLeft() left}, {@link #getTop() top},
* {@link #getRight() right} and {@link #getBottom() bottom}.
+ *
+ * @hide
*/
public static final int CLIP_BOUNDS = 0;
@@ -356,6 +358,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* Optical bounds describe where a widget appears to be. They sit inside the clip
* bounds which need to cover a larger area to allow other effects,
* such as shadows and glows, to be drawn.
+ *
+ * @hide
*/
public static final int OPTICAL_BOUNDS = 1;
@@ -4539,6 +4543,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @return the layout mode to use during layout operations
*
* @see #setLayoutMode(int)
+ *
+ * @hide
*/
public int getLayoutMode() {
return mLayoutMode;
@@ -4553,6 +4559,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @param layoutMode the layout mode to use during layout operations
*
* @see #getLayoutMode()
+ *
+ * @hide
*/
public void setLayoutMode(int layoutMode) {
if (mLayoutMode != layoutMode) {
@@ -5229,6 +5237,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
+ /**
+ * @hide
+ */
@Override
public void onResolvedLayoutDirectionReset() {
// Take care of resetting the children resolution too
@@ -5241,6 +5252,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
+ /**
+ * @hide
+ */
@Override
public void onResolvedTextDirectionReset() {
// Take care of resetting the children resolution too
@@ -5253,6 +5267,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
+ /**
+ * @hide
+ */
@Override
public void onResolvedTextAlignmentReset() {
// Take care of resetting the children resolution too
@@ -5443,6 +5460,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*
* {@link View#LAYOUT_DIRECTION_LTR}
* {@link View#LAYOUT_DIRECTION_RTL}
+ * @hide
*/
public void onResolveLayoutDirection(int layoutDirection) {
}
@@ -5534,6 +5552,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* The start margin in pixels of the child.
* Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
* to this field.
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public int startMargin = DEFAULT_RELATIVE;
@@ -5542,6 +5561,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* The end margin in pixels of the child.
* Call {@link ViewGroup#setLayoutParams(LayoutParams)} after reassigning a new value
* to this field.
+ * @hide
*/
@ViewDebug.ExportedProperty(category = "layout")
public int endMargin = DEFAULT_RELATIVE;
@@ -5660,7 +5680,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginTop
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginBottom
- *
* @hide
*/
public void setMarginsRelative(int start, int top, int end, int bottom) {
@@ -5676,6 +5695,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginStart
*
* @return the start margin in pixels.
+ * @hide
*/
public int getMarginStart() {
return startMargin;
@@ -5687,6 +5707,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
*
* @return the end margin in pixels.
+ * @hide
*/
public int getMarginEnd() {
return endMargin;
@@ -5699,6 +5720,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
* @attr ref android.R.styleable#ViewGroup_MarginLayout_layout_marginEnd
*
* @return true if either marginStart or marginEnd has been set
+ * @hide
*/
public boolean isMarginRelative() {
return (startMargin != DEFAULT_RELATIVE) || (endMargin != DEFAULT_RELATIVE);
@@ -5707,6 +5729,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
/**
* This will be called by {@link android.view.View#requestLayout()}. Left and Right margins
* may be overridden depending on layout direction.
+ * @hide
*/
@Override
public void onResolveLayoutDirection(int layoutDirection) {
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index ec37acf..2012db2 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -624,14 +624,20 @@ public class ViewPropertyAnimator {
/**
* The View associated with this ViewPropertyAnimator will have its
* {@link View#setLayerType(int, android.graphics.Paint) layer type} set to
- * {@link View#LAYER_TYPE_HARDWARE} for the duration of the next animation. This state
- * is not persistent, either on the View or on this ViewPropertyAnimator: the layer type
- * of the View will be restored when the animation ends to what it was when this method was
- * called, and this setting on ViewPropertyAnimator is only valid for the next animation.
- * Note that calling this method and then independently setting the layer type of the View
- * (by a direct call to {@link View#setLayerType(int, android.graphics.Paint)}) will result
- * in some inconsistency, including having the layer type restored to its pre-withLayer()
- * value when the animation ends.
+ * {@link View#LAYER_TYPE_HARDWARE} for the duration of the next animation.
+ * As stated in the documentation for {@link View#LAYER_TYPE_HARDWARE},
+ * the actual type of layer used internally depends on the runtime situation of the
+ * view. If the activity and this view are hardware-accelerated, then the layer will be
+ * accelerated as well. If the activity or the view is not accelerated, then the layer will
+ * effectively be the same as {@link View#LAYER_TYPE_SOFTWARE}.
+ *
+ * <p>This state is not persistent, either on the View or on this ViewPropertyAnimator: the
+ * layer type of the View will be restored when the animation ends to what it was when this
+ * method was called, and this setting on ViewPropertyAnimator is only valid for the next
+ * animation. Note that calling this method and then independently setting the layer type of
+ * the View (by a direct call to {@link View#setLayerType(int, android.graphics.Paint)}) will
+ * result in some inconsistency, including having the layer type restored to its pre-withLayer()
+ * value when the animation ends.</p>
*
* @see View#setLayerType(int, android.graphics.Paint)
* @return This object, allowing calls to methods in this class to be chained.
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e1d821f..ec6bd81 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -230,6 +230,7 @@ public final class ViewRootImpl implements ViewParent,
boolean mHasHadWindowFocus;
boolean mLastWasImTarget;
boolean mWindowsAnimating;
+ boolean mIsDrawing;
int mLastSystemUiVisibility;
// Pool of queued input events.
@@ -262,6 +263,7 @@ public final class ViewRootImpl implements ViewParent,
final Rect mPendingVisibleInsets = new Rect();
final Rect mPendingContentInsets = new Rect();
final Rect mPendingSystemInsets = new Rect();
+ final Rect mActiveRect = new Rect();
final ViewTreeObserver.InternalInsetsInfo mLastGivenInsets
= new ViewTreeObserver.InternalInsetsInfo();
@@ -271,7 +273,8 @@ public final class ViewRootImpl implements ViewParent,
final Configuration mPendingConfiguration = new Configuration();
class ResizedInfo {
- Rect coveredInsets;
+ Rect systemInsets;
+ Rect contentInsets;
Rect visibleInsets;
Configuration newConfig;
}
@@ -567,6 +570,7 @@ public final class ViewRootImpl implements ViewParent,
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
}
+ mPendingSystemInsets.set(0, 0, 0, 0);
mPendingContentInsets.set(mAttachInfo.mContentInsets);
mPendingVisibleInsets.set(0, 0, 0, 0);
if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
@@ -763,6 +767,9 @@ public final class ViewRootImpl implements ViewParent,
// preserve compatible window flag if exists.
int compatibleWindowFlag =
mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
+ // transfer over system UI visibility values as they carry current state.
+ attrs.systemUiVisibility = mWindowAttributes.systemUiVisibility;
+ attrs.subtreeSystemUiVisibility = mWindowAttributes.subtreeSystemUiVisibility;
mWindowAttributesChangesFlag = mWindowAttributes.copyFrom(attrs);
mWindowAttributes.flags |= compatibleWindowFlag;
@@ -1019,6 +1026,7 @@ public final class ViewRootImpl implements ViewParent,
attachInfo.mSystemUiVisibility = 0;
attachInfo.mHasSystemUiListeners = false;
mView.dispatchCollectViewAttributes(attachInfo, 0);
+ attachInfo.mSystemUiVisibility &= ~attachInfo.mDisabledSystemUiVisibility;
if (attachInfo.mKeepScreenOn != oldScreenOn
|| attachInfo.mSystemUiVisibility != oldVis
|| attachInfo.mHasSystemUiListeners != oldHasSystemUiListeners) {
@@ -1219,6 +1227,7 @@ public final class ViewRootImpl implements ViewParent,
getRunQueue().executeActions(attachInfo.mHandler);
boolean insetsChanged = false;
+ boolean activeRectChanged = false;
boolean layoutRequested = mLayoutRequested && !mStopped;
if (layoutRequested) {
@@ -1230,7 +1239,12 @@ public final class ViewRootImpl implements ViewParent,
// to opposite of the added touch mode.
mAttachInfo.mInTouchMode = !mAddedTouchMode;
ensureTouchModeLocally(mAddedTouchMode);
+ activeRectChanged = true;
} else {
+ if (!mPendingSystemInsets.equals(mAttachInfo.mSystemInsets)) {
+ mAttachInfo.mSystemInsets.set(mPendingSystemInsets);
+ activeRectChanged = true;
+ }
if (!mPendingContentInsets.equals(mAttachInfo.mContentInsets)) {
insetsChanged = true;
}
@@ -1383,7 +1397,11 @@ public final class ViewRootImpl implements ViewParent,
updateConfiguration(mPendingConfiguration, !mFirst);
mPendingConfiguration.seq = 0;
}
-
+
+ if (!mPendingSystemInsets.equals(mAttachInfo.mSystemInsets)) {
+ activeRectChanged = true;
+ mAttachInfo.mSystemInsets.set(mPendingSystemInsets);
+ }
contentInsetsChanged = !mPendingContentInsets.equals(
mAttachInfo.mContentInsets);
visibleInsetsChanged = !mPendingVisibleInsets.equals(
@@ -1486,6 +1504,7 @@ public final class ViewRootImpl implements ViewParent,
// before actually drawing them, so it can display then
// all at once.
newSurface = true;
+ activeRectChanged = true;
mFullRedrawNeeded = true;
mPreviousTransparentRegion.setEmpty();
@@ -1550,8 +1569,11 @@ public final class ViewRootImpl implements ViewParent,
// !!FIXME!! This next section handles the case where we did not get the
// window size we asked for. We should avoid this by getting a maximum size from
// the window session beforehand.
- mWidth = frame.width();
- mHeight = frame.height();
+ if (mWidth != frame.width() || mHeight != frame.height()) {
+ activeRectChanged = true;
+ mWidth = frame.width();
+ mHeight = frame.height();
+ }
if (mSurfaceHolder != null) {
// The app owns the surface; tell it about what is going on.
@@ -1667,6 +1689,14 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ if (activeRectChanged && mSurface.isValid()) {
+ mActiveRect.set(attachInfo.mSystemInsets.left, attachInfo.mSystemInsets.top,
+ mWidth - attachInfo.mSystemInsets.right,
+ mHeight - attachInfo.mSystemInsets.bottom);
+ //Log.i(TAG, "Active rect " + mWindowAttributes.getTitle() + ": " + mActiveRect);
+ mSurface.setActiveRect(mActiveRect);
+ }
+
final boolean didLayout = layoutRequested && !mStopped;
boolean triggerGlobalLayoutListener = didLayout
|| attachInfo.mRecomputeGlobalAttributes;
@@ -2009,10 +2039,12 @@ public final class ViewRootImpl implements ViewParent,
final boolean fullRedrawNeeded = mFullRedrawNeeded;
mFullRedrawNeeded = false;
+ mIsDrawing = true;
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "draw");
try {
draw(fullRedrawNeeded);
} finally {
+ mIsDrawing = false;
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
@@ -2781,7 +2813,8 @@ public final class ViewRootImpl implements ViewParent,
ResizedInfo ri = (ResizedInfo)msg.obj;
if (mWinFrame.width() == msg.arg1 && mWinFrame.height() == msg.arg2
- && mPendingContentInsets.equals(ri.coveredInsets)
+ && mPendingSystemInsets.equals(ri.systemInsets)
+ && mPendingContentInsets.equals(ri.contentInsets)
&& mPendingVisibleInsets.equals(ri.visibleInsets)
&& ((ResizedInfo)msg.obj).newConfig == null) {
break;
@@ -2797,7 +2830,8 @@ public final class ViewRootImpl implements ViewParent,
mWinFrame.right = msg.arg1;
mWinFrame.top = 0;
mWinFrame.bottom = msg.arg2;
- mPendingContentInsets.set(((ResizedInfo)msg.obj).coveredInsets);
+ mPendingSystemInsets.set(((ResizedInfo)msg.obj).systemInsets);
+ mPendingContentInsets.set(((ResizedInfo)msg.obj).contentInsets);
mPendingVisibleInsets.set(((ResizedInfo)msg.obj).visibleInsets);
if (msg.what == MSG_RESIZED_REPORT) {
mReportNextDraw = true;
@@ -3932,7 +3966,12 @@ public final class ViewRootImpl implements ViewParent,
if (immediate) {
doDie();
} else {
- destroyHardwareRenderer();
+ if (!mIsDrawing) {
+ destroyHardwareRenderer();
+ } else {
+ Log.e(TAG, "Attempting to destroy the window while drawing!\n" +
+ " window=" + this + ", title=" + mWindowAttributes.getTitle());
+ }
mHandler.sendEmptyMessage(MSG_DIE);
}
}
@@ -4006,15 +4045,16 @@ public final class ViewRootImpl implements ViewParent,
mHandler.sendMessage(msg);
}
- public void dispatchResized(int w, int h, Rect coveredInsets,
+ public void dispatchResized(int w, int h, Rect systemInsets, Rect contentInsets,
Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
if (DEBUG_LAYOUT) Log.v(TAG, "Resizing " + this + ": w=" + w
- + " h=" + h + " coveredInsets=" + coveredInsets.toShortString()
+ + " h=" + h + " systemInsets=" + systemInsets.toShortString()
+ + " contentInsets=" + contentInsets.toShortString()
+ " visibleInsets=" + visibleInsets.toShortString()
+ " reportDraw=" + reportDraw);
Message msg = mHandler.obtainMessage(reportDraw ? MSG_RESIZED_REPORT :MSG_RESIZED);
if (mTranslator != null) {
- mTranslator.translateRectInScreenToAppWindow(coveredInsets);
+ mTranslator.translateRectInScreenToAppWindow(contentInsets);
mTranslator.translateRectInScreenToAppWindow(visibleInsets);
w *= mTranslator.applicationInvertedScale;
h *= mTranslator.applicationInvertedScale;
@@ -4022,7 +4062,8 @@ public final class ViewRootImpl implements ViewParent,
msg.arg1 = w;
msg.arg2 = h;
ResizedInfo ri = new ResizedInfo();
- ri.coveredInsets = new Rect(coveredInsets);
+ ri.systemInsets = new Rect(systemInsets);
+ ri.contentInsets = new Rect(contentInsets);
ri.visibleInsets = new Rect(visibleInsets);
ri.newConfig = newConfig;
msg.obj = ri;
@@ -4673,8 +4714,8 @@ public final class ViewRootImpl implements ViewParent,
Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
- viewAncestor.dispatchResized(w, h, contentInsets, visibleInsets, reportDraw,
- newConfig);
+ viewAncestor.dispatchResized(w, h, systemInsets, contentInsets,
+ visibleInsets, reportDraw, newConfig);
}
}
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 6d1166e..f70ffa9 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -226,9 +226,9 @@ import java.util.List;
* <li>{@link #getContentDescription()} - The content description of the source.</li>
* </ul>
* </p>
- * <b>View text traversed at granularity</b> - represents the event of traversing the
+ * <b>View text traversed at movement granularity</b> - represents the event of traversing the
* text of a view at a given granularity. For example, moving to the next word.</br>
- * <em>Type:</em> {@link #TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY} </br>
+ * <em>Type:</em> {@link #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY} </br>
* <em>Properties:</em></br>
* <ul>
* <li>{@link #getEventType()} - The type of the event.</li>
@@ -236,11 +236,12 @@ import java.util.List;
* <li>{@link #getClassName()} - The class name of the source.</li>
* <li>{@link #getPackageName()} - The package name of the source.</li>
* <li>{@link #getEventTime()} - The event time.</li>
- * <li>{@link #getText()} - The text of the current text at the granularity.</li>
+ * <li>{@link #getText()} - The text of the current text at the movement granularity.</li>
* <li>{@link #isPassword()} - Whether the source is password.</li>
* <li>{@link #isEnabled()} - Whether the source is enabled.</li>
* <li>{@link #getContentDescription()} - The content description of the source.</li>
- * <li>{@link #getGranularity()} - Sets the granularity at which a view's text was traversed.</li>
+ * <li>{@link #getMovementGranularity()} - Sets the granularity at which a view's text
+ * was traversed.</li>
* </ul>
* </p>
* <p>
@@ -597,9 +598,9 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public static final int TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED = 0x00010000;
/**
- * Represents the event of traversing the text of a view at a given granularity.
+ * Represents the event of traversing the text of a view at a given movement granularity.
*/
- public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY = 0x00020000;
+ public static final int TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY = 0x00020000;
/**
* Mask for {@link AccessibilityEvent} all types.
@@ -619,7 +620,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* @see #TYPE_VIEW_SCROLLED
* @see #TYPE_VIEW_TEXT_SELECTION_CHANGED
* @see #TYPE_ANNOUNCEMENT
- * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY
+ * @see #TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY
*/
public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
@@ -633,7 +634,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
private int mEventType;
private CharSequence mPackageName;
private long mEventTime;
- int mGranularity;
+ int mMovementGranularity;
private final ArrayList<AccessibilityRecord> mRecords = new ArrayList<AccessibilityRecord>();
@@ -651,7 +652,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
void init(AccessibilityEvent event) {
super.init(event);
mEventType = event.mEventType;
- mGranularity = event.mGranularity;
+ mMovementGranularity = event.mMovementGranularity;
mEventTime = event.mEventTime;
mPackageName = event.mPackageName;
}
@@ -769,24 +770,24 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
}
/**
- * Sets the text granularity that was traversed.
+ * Sets the movement granularity that was traversed.
*
* @param granularity The granularity.
*
* @throws IllegalStateException If called from an AccessibilityService.
*/
- public void setGranularity(int granularity) {
+ public void setMovementGranularity(int granularity) {
enforceNotSealed();
- mGranularity = granularity;
+ mMovementGranularity = granularity;
}
/**
- * Gets the text granularity that was traversed.
+ * Gets the movement granularity that was traversed.
*
* @return The granularity.
*/
- public int getGranularity() {
- return mGranularity;
+ public int getMovementGranularity() {
+ return mMovementGranularity;
}
/**
@@ -877,7 +878,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
protected void clear() {
super.clear();
mEventType = 0;
- mGranularity = 0;
+ mMovementGranularity = 0;
mPackageName = null;
mEventTime = 0;
while (!mRecords.isEmpty()) {
@@ -894,7 +895,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public void initFromParcel(Parcel parcel) {
mSealed = (parcel.readInt() == 1);
mEventType = parcel.readInt();
- mGranularity = parcel.readInt();
+ mMovementGranularity = parcel.readInt();
mPackageName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
mEventTime = parcel.readLong();
mConnectionId = parcel.readInt();
@@ -945,7 +946,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public void writeToParcel(Parcel parcel, int flags) {
parcel.writeInt(isSealed() ? 1 : 0);
parcel.writeInt(mEventType);
- parcel.writeInt(mGranularity);
+ parcel.writeInt(mMovementGranularity);
TextUtils.writeToParcel(mPackageName, parcel, 0);
parcel.writeLong(mEventTime);
parcel.writeInt(mConnectionId);
@@ -1002,7 +1003,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
builder.append("EventType: ").append(eventTypeToString(mEventType));
builder.append("; EventTime: ").append(mEventTime);
builder.append("; PackageName: ").append(mPackageName);
- builder.append("; Granularity: ").append(mGranularity);
+ builder.append("; MovementGranularity: ").append(mMovementGranularity);
builder.append(super.toString());
if (DEBUG) {
builder.append("\n");
@@ -1083,8 +1084,8 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
return "TYPE_VIEW_ACCESSIBILITY_FOCUSED";
case TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
return "TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED";
- case TYPE_VIEW_TEXT_TRAVERSED_AT_GRANULARITY:
- return "TYPE_CURRENT_AT_GRANULARITY_CHANGED";
+ case TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY:
+ return "TYPE_CURRENT_AT_GRANULARITY_MOVEMENT_CHANGED";
default:
return null;
}
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 5266c83..c0696a9 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -123,53 +123,56 @@ public class AccessibilityNodeInfo implements Parcelable {
/**
* Action that requests to go to the next entity in this node's text
- * at a given granularity. For example, move to the next character, word, etc.
+ * at a given movement granularity. For example, move to the next character,
+ * word, etc.
* <p>
- * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_GRANULARITY_INT}<br>
+ * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br>
* <strong>Example:</strong>
* <code><pre><p>
* Bundle arguments = new Bundle();
- * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT,
- * AccessibilityNodeInfo.GRANULARITY_CHARACTER);
- * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_GRANULARITY, arguments);
+ * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ * info.performAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY, arguments);
* </code></pre></p>
* </p>
*
- * @see #setGranularities(int)
- * @see #getGranularities()
+ * @see #setMovementGranularities(int)
+ * @see #getMovementGranularities()
*
- * @see #GRANULARITY_CHARACTER
- * @see #GRANULARITY_WORD
- * @see #GRANULARITY_LINE
- * @see #GRANULARITY_PARAGRAPH
- * @see #GRANULARITY_PAGE
+ * @see #MOVEMENT_GRANULARITY_CHARACTER
+ * @see #MOVEMENT_GRANULARITY_WORD
+ * @see #MOVEMENT_GRANULARITY_LINE
+ * @see #MOVEMENT_GRANULARITY_PARAGRAPH
+ * @see #MOVEMENT_GRANULARITY_PAGE
*/
- public static final int ACTION_NEXT_AT_GRANULARITY = 0x00000100;
+ public static final int ACTION_NEXT_AT_MOVEMENT_GRANULARITY = 0x00000100;
/**
* Action that requests to go to the previous entity in this node's text
- * at a given granularity. For example, move to the next character, word, etc.
+ * at a given movement granularity. For example, move to the next character,
+ * word, etc.
* <p>
- * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_GRANULARITY_INT}<br>
+ * <strong>Arguments:</strong> {@link #ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT}<br>
* <strong>Example:</strong>
* <code><pre><p>
* Bundle arguments = new Bundle();
- * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_GRANULARITY_INT,
- * AccessibilityNodeInfo.GRANULARITY_CHARACTER);
- * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_GRANULARITY, arguments);
+ * arguments.putInt(AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT,
+ * AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER);
+ * info.performAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
+ * arguments);
* </code></pre></p>
* </p>
*
- * @see #setGranularities(int)
- * @see #getGranularities()
+ * @see #setMovementGranularities(int)
+ * @see #getMovementGranularities()
*
- * @see #GRANULARITY_CHARACTER
- * @see #GRANULARITY_WORD
- * @see #GRANULARITY_LINE
- * @see #GRANULARITY_PARAGRAPH
- * @see #GRANULARITY_PAGE
+ * @see #MOVEMENT_GRANULARITY_CHARACTER
+ * @see #MOVEMENT_GRANULARITY_WORD
+ * @see #MOVEMENT_GRANULARITY_LINE
+ * @see #MOVEMENT_GRANULARITY_PARAGRAPH
+ * @see #MOVEMENT_GRANULARITY_PAGE
*/
- public static final int ACTION_PREVIOUS_AT_GRANULARITY = 0x00000200;
+ public static final int ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY = 0x00000200;
/**
* Action to move to the next HTML element of a given type. For example, move
@@ -202,14 +205,15 @@ public class AccessibilityNodeInfo implements Parcelable {
public static final int ACTION_PREVIOUS_HTML_ELEMENT = 0x00000800;
/**
- * Argument for which text granularity to be used when traversing the node text.
+ * Argument for which movement granularity to be used when traversing the node text.
* <p>
* <strong>Type:</strong> int<br>
- * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_GRANULARITY},
- * {@link #ACTION_PREVIOUS_AT_GRANULARITY}
+ * <strong>Actions:</strong> {@link #ACTION_NEXT_AT_MOVEMENT_GRANULARITY},
+ * {@link #ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY}
* </p>
*/
- public static final String ACTION_ARGUMENT_GRANULARITY_INT = "ACTION_ARGUMENT_GRANULARITY_INT";
+ public static final String ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT =
+ "ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT";
/**
* Argument for which HTML element to get moving to the next/previous HTML element.
@@ -232,32 +236,32 @@ public class AccessibilityNodeInfo implements Parcelable {
*/
public static final int FOCUS_ACCESSIBILITY = 2;
- // Granularities
+ // Movement granularities
/**
- * Granularity bit for traversing the text of a node by character.
+ * Movement granularity bit for traversing the text of a node by character.
*/
- public static final int GRANULARITY_CHARACTER = 0x00000001;
+ public static final int MOVEMENT_GRANULARITY_CHARACTER = 0x00000001;
/**
- * Granularity bit for traversing the text of a node by word.
+ * Movement granularity bit for traversing the text of a node by word.
*/
- public static final int GRANULARITY_WORD = 0x00000002;
+ public static final int MOVEMENT_GRANULARITY_WORD = 0x00000002;
/**
- * Granularity bit for traversing the text of a node by line.
+ * Movement granularity bit for traversing the text of a node by line.
*/
- public static final int GRANULARITY_LINE = 0x00000004;
+ public static final int MOVEMENT_GRANULARITY_LINE = 0x00000004;
/**
- * Granularity bit for traversing the text of a node by paragraph.
+ * Movement granularity bit for traversing the text of a node by paragraph.
*/
- public static final int GRANULARITY_PARAGRAPH = 0x00000008;
+ public static final int MOVEMENT_GRANULARITY_PARAGRAPH = 0x00000008;
/**
- * Granularity bit for traversing the text of a node by page.
+ * Movement granularity bit for traversing the text of a node by page.
*/
- public static final int GRANULARITY_PAGE = 0x00000010;
+ public static final int MOVEMENT_GRANULARITY_PAGE = 0x00000010;
// Boolean attributes.
@@ -362,7 +366,7 @@ public class AccessibilityNodeInfo implements Parcelable {
private final SparseLongArray mChildNodeIds = new SparseLongArray();
private int mActions;
- private int mGranularities;
+ private int mMovementGranularities;
private int mConnectionId = UNDEFINED;
@@ -586,7 +590,7 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
- * Sets the text granularities for traversing the text of this node.
+ * Sets the movement granularities for traversing the text of this node.
* <p>
* <strong>Note:</strong> Cannot be called from an
* {@link android.accessibilityservice.AccessibilityService}.
@@ -597,18 +601,18 @@ public class AccessibilityNodeInfo implements Parcelable {
*
* @throws IllegalStateException If called from an AccessibilityService.
*/
- public void setGranularities(int granularities) {
+ public void setMovementGranularities(int granularities) {
enforceNotSealed();
- mGranularities = granularities;
+ mMovementGranularities = granularities;
}
/**
- * Gets the granularities for traversing the text of this node.
+ * Gets the movement granularities for traversing the text of this node.
*
* @return The bit mask with granularities.
*/
- public int getGranularities() {
- return mGranularities;
+ public int getMovementGranularities() {
+ return mMovementGranularities;
}
/**
@@ -1412,7 +1416,7 @@ public class AccessibilityNodeInfo implements Parcelable {
parcel.writeInt(mActions);
- parcel.writeInt(mGranularities);
+ parcel.writeInt(mMovementGranularities);
parcel.writeInt(mBooleanProperties);
@@ -1446,7 +1450,7 @@ public class AccessibilityNodeInfo implements Parcelable {
mContentDescription = other.mContentDescription;
mActions= other.mActions;
mBooleanProperties = other.mBooleanProperties;
- mGranularities = other.mGranularities;
+ mMovementGranularities = other.mMovementGranularities;
final int otherChildIdCount = other.mChildNodeIds.size();
for (int i = 0; i < otherChildIdCount; i++) {
mChildNodeIds.put(i, other.mChildNodeIds.valueAt(i));
@@ -1484,7 +1488,7 @@ public class AccessibilityNodeInfo implements Parcelable {
mActions = parcel.readInt();
- mGranularities = parcel.readInt();
+ mMovementGranularities = parcel.readInt();
mBooleanProperties = parcel.readInt();
@@ -1503,7 +1507,7 @@ public class AccessibilityNodeInfo implements Parcelable {
mParentNodeId = ROOT_NODE_ID;
mWindowId = UNDEFINED;
mConnectionId = UNDEFINED;
- mGranularities = 0;
+ mMovementGranularities = 0;
mChildNodeIds.clear();
mBoundsInParent.set(0, 0, 0, 0);
mBoundsInScreen.set(0, 0, 0, 0);
@@ -1539,10 +1543,10 @@ public class AccessibilityNodeInfo implements Parcelable {
return "ACTION_ACCESSIBILITY_FOCUS";
case ACTION_CLEAR_ACCESSIBILITY_FOCUS:
return "ACTION_CLEAR_ACCESSIBILITY_FOCUS";
- case ACTION_NEXT_AT_GRANULARITY:
- return "ACTION_NEXT_AT_GRANULARITY";
- case ACTION_PREVIOUS_AT_GRANULARITY:
- return "ACTION_PREVIOUS_AT_GRANULARITY";
+ case ACTION_NEXT_AT_MOVEMENT_GRANULARITY:
+ return "ACTION_NEXT_AT_MOVEMENT_GRANULARITY";
+ case ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY:
+ return "ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY";
case ACTION_NEXT_HTML_ELEMENT:
return "ACTION_NEXT_HTML_ELEMENT";
case ACTION_PREVIOUS_HTML_ELEMENT:
@@ -1553,25 +1557,25 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
- * Gets the human readable granularity symbolic name.
+ * Gets the human readable movement granularity symbolic name.
*
- * @param granularity The action.
+ * @param granularity The granularity.
* @return The symbolic name.
*/
- private static String getGranularitySymbolicName(int granularity) {
+ private static String getMovementGranularitySymbolicName(int granularity) {
switch (granularity) {
- case GRANULARITY_CHARACTER:
- return "GRANULARITY_CHARACTER";
- case GRANULARITY_WORD:
- return "GRANULARITY_WORD";
- case GRANULARITY_LINE:
- return "GRANULARITY_LINE";
- case GRANULARITY_PARAGRAPH:
- return "GRANULARITY_PARAGRAPH";
- case GRANULARITY_PAGE:
- return "GRANULARITY_PAGE";
+ case MOVEMENT_GRANULARITY_CHARACTER:
+ return "MOVEMENT_GRANULARITY_CHARACTER";
+ case MOVEMENT_GRANULARITY_WORD:
+ return "MOVEMENT_GRANULARITY_WORD";
+ case MOVEMENT_GRANULARITY_LINE:
+ return "MOVEMENT_GRANULARITY_LINE";
+ case MOVEMENT_GRANULARITY_PARAGRAPH:
+ return "MOVEMENT_GRANULARITY_PARAGRAPH";
+ case MOVEMENT_GRANULARITY_PAGE:
+ return "MOVEMENT_GRANULARITY_PAGE";
default:
- throw new IllegalArgumentException("Unknown granularity: " + granularity);
+ throw new IllegalArgumentException("Unknown movement granularity: " + granularity);
}
}
@@ -1622,12 +1626,12 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; virtualDescendantId: " + getVirtualDescendantId(mSourceNodeId));
builder.append("; mParentNodeId: " + mParentNodeId);
- int granularities = mGranularities;
- builder.append("; granularities: [");
+ int granularities = mMovementGranularities;
+ builder.append("; MovementGranularities: [");
while (granularities != 0) {
final int granularity = 1 << Integer.numberOfTrailingZeros(granularities);
granularities &= ~granularity;
- builder.append(getGranularitySymbolicName(granularity));
+ builder.append(getMovementGranularitySymbolicName(granularity));
if (granularities != 0) {
builder.append(", ");
}
diff --git a/core/java/android/webkit/AutoCompletePopup.java b/core/java/android/webkit/AutoCompletePopup.java
index 21d5e02..87e878b 100644
--- a/core/java/android/webkit/AutoCompletePopup.java
+++ b/core/java/android/webkit/AutoCompletePopup.java
@@ -28,12 +28,15 @@ import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ListAdapter;
import android.widget.ListPopupWindow;
+import android.widget.PopupWindow.OnDismissListener;
-class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
+class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener,
+ OnDismissListener{
private static class AnchorView extends View {
AnchorView(Context context) {
super(context);
setFocusable(false);
+ setVisibility(INVISIBLE);
}
}
private static final int AUTOFILL_FORM = 100;
@@ -48,17 +51,10 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
private WebViewClassic.WebViewInputConnection mInputConnection;
private WebViewClassic mWebView;
- public AutoCompletePopup(Context context,
- WebViewClassic webView,
+ public AutoCompletePopup(WebViewClassic webView,
WebViewClassic.WebViewInputConnection inputConnection) {
mInputConnection = inputConnection;
mWebView = webView;
- mPopup = new ListPopupWindow(context);
- mAnchor = new AnchorView(context);
- mWebView.getWebView().addView(mAnchor);
- mPopup.setOnItemClickListener(this);
- mPopup.setAnchorView(mAnchor);
- mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW);
mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -72,6 +68,9 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
}
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ if (mPopup == null) {
+ return false;
+ }
if (keyCode == KeyEvent.KEYCODE_BACK && mPopup.isShowing()) {
// special case for the back key, we do not even try to send it
// to the drop down list but instead, consume it immediately
@@ -112,11 +111,14 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
public void clearAdapter() {
mAdapter = null;
mFilter = null;
- mPopup.dismiss();
- mPopup.setAdapter(null);
+ if (mPopup != null) {
+ mPopup.dismiss();
+ mPopup.setAdapter(null);
+ }
}
public <T extends ListAdapter & Filterable> void setAdapter(T adapter) {
+ ensurePopup();
mPopup.setAdapter(adapter);
mAdapter = adapter;
if (adapter != null) {
@@ -129,6 +131,7 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
}
public void resetRect() {
+ ensurePopup();
int left = mWebView.contentToViewX(mWebView.mEditTextContentBounds.left);
int right = mWebView.contentToViewX(mWebView.mEditTextContentBounds.right);
int width = right - left;
@@ -164,6 +167,9 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
// AdapterView.OnItemClickListener implementation
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (mPopup == null) {
+ return;
+ }
if (id == 0 && position == 0 && mInputConnection.getIsAutoFillable()) {
mText = "";
pushTextToInputConnection();
@@ -206,6 +212,7 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
@Override
public void onFilterComplete(int count) {
+ ensurePopup();
boolean showDropDown = (count > 0) &&
(mInputConnection.getIsAutoFillable() || mText.length() > 0);
if (showDropDown) {
@@ -219,5 +226,23 @@ class AutoCompletePopup implements OnItemClickListener, Filter.FilterListener {
mPopup.dismiss();
}
}
+
+ @Override
+ public void onDismiss() {
+ mWebView.getWebView().removeView(mAnchor);
+ }
+
+ private void ensurePopup() {
+ if (mPopup == null) {
+ mPopup = new ListPopupWindow(mWebView.getContext());
+ mAnchor = new AnchorView(mWebView.getContext());
+ mWebView.getWebView().addView(mAnchor);
+ mPopup.setOnItemClickListener(this);
+ mPopup.setAnchorView(mAnchor);
+ mPopup.setPromptPosition(ListPopupWindow.POSITION_PROMPT_BELOW);
+ } else if (mWebView.getWebView().indexOfChild(mAnchor) < 0) {
+ mWebView.getWebView().addView(mAnchor);
+ }
+ }
}
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index c169de4..fe812af 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -56,6 +56,8 @@ import java.util.Map;
import java.util.Set;
import org.apache.harmony.security.provider.cert.X509CertImpl;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
class BrowserFrame extends Handler {
@@ -1104,12 +1106,23 @@ class BrowserFrame extends Handler {
SslClientCertLookupTable table = SslClientCertLookupTable.getInstance();
if (table.IsAllowed(hostAndPort)) {
// previously allowed
- nativeSslClientCert(handle,
- table.PrivateKey(hostAndPort),
- table.CertificateChain(hostAndPort));
+ PrivateKey pkey = table.PrivateKey(hostAndPort);
+ if (pkey instanceof OpenSSLRSAPrivateKey) {
+ nativeSslClientCert(handle,
+ ((OpenSSLRSAPrivateKey)pkey).getPkeyContext(),
+ table.CertificateChain(hostAndPort));
+ } else if (pkey instanceof OpenSSLDSAPrivateKey) {
+ nativeSslClientCert(handle,
+ ((OpenSSLDSAPrivateKey)pkey).getPkeyContext(),
+ table.CertificateChain(hostAndPort));
+ } else {
+ nativeSslClientCert(handle,
+ pkey.getEncoded(),
+ table.CertificateChain(hostAndPort));
+ }
} else if (table.IsDenied(hostAndPort)) {
// previously denied
- nativeSslClientCert(handle, null, null);
+ nativeSslClientCert(handle, 0, null);
} else {
// previously ignored or new
mCallbackProxy.onReceivedClientCertRequest(
@@ -1296,7 +1309,11 @@ class BrowserFrame extends Handler {
private native void nativeSslCertErrorCancel(int handle, int certError);
native void nativeSslClientCert(int handle,
- byte[] pkcs8EncodedPrivateKey,
+ int ctx,
+ byte[][] asn1DerEncodedCertificateChain);
+
+ native void nativeSslClientCert(int handle,
+ byte[] pkey,
byte[][] asn1DerEncodedCertificateChain);
/**
diff --git a/core/java/android/webkit/ClientCertRequestHandler.java b/core/java/android/webkit/ClientCertRequestHandler.java
index f862613..6570a9b8 100644
--- a/core/java/android/webkit/ClientCertRequestHandler.java
+++ b/core/java/android/webkit/ClientCertRequestHandler.java
@@ -21,6 +21,8 @@ import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import org.apache.harmony.xnet.provider.jsse.NativeCrypto;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLDSAPrivateKey;
+import org.apache.harmony.xnet.provider.jsse.OpenSSLRSAPrivateKey;
/**
* ClientCertRequestHandler: class responsible for handling client
@@ -50,20 +52,23 @@ public final class ClientCertRequestHandler extends Handler {
* Proceed with the specified private key and client certificate chain.
*/
public void proceed(PrivateKey privateKey, X509Certificate[] chain) {
- final byte[] privateKeyBytes = privateKey.getEncoded();
- final byte[][] chainBytes;
try {
- chainBytes = NativeCrypto.encodeCertificates(chain);
- mTable.Allow(mHostAndPort, privateKeyBytes, chainBytes);
- post(new Runnable() {
- public void run() {
- mBrowserFrame.nativeSslClientCert(mHandle, privateKeyBytes, chainBytes);
- }
- });
+ byte[][] chainBytes = NativeCrypto.encodeCertificates(chain);
+ mTable.Allow(mHostAndPort, privateKey, chainBytes);
+
+ if (privateKey instanceof OpenSSLRSAPrivateKey) {
+ setSslClientCertFromCtx(((OpenSSLRSAPrivateKey)privateKey).getPkeyContext(),
+ chainBytes);
+ } else if (privateKey instanceof OpenSSLDSAPrivateKey) {
+ setSslClientCertFromCtx(((OpenSSLDSAPrivateKey)privateKey).getPkeyContext(),
+ chainBytes);
+ } else {
+ setSslClientCertFromPKCS8(privateKey.getEncoded(),chainBytes);
+ }
} catch (CertificateEncodingException e) {
post(new Runnable() {
public void run() {
- mBrowserFrame.nativeSslClientCert(mHandle, null, null);
+ mBrowserFrame.nativeSslClientCert(mHandle, 0, null);
return;
}
});
@@ -71,12 +76,34 @@ public final class ClientCertRequestHandler extends Handler {
}
/**
+ * Proceed with the specified private key bytes and client certificate chain.
+ */
+ private void setSslClientCertFromCtx(final int ctx, final byte[][] chainBytes) {
+ post(new Runnable() {
+ public void run() {
+ mBrowserFrame.nativeSslClientCert(mHandle, ctx, chainBytes);
+ }
+ });
+ }
+
+ /**
+ * Proceed with the specified private key context and client certificate chain.
+ */
+ private void setSslClientCertFromPKCS8(final byte[] key, final byte[][] chainBytes) {
+ post(new Runnable() {
+ public void run() {
+ mBrowserFrame.nativeSslClientCert(mHandle, key, chainBytes);
+ }
+ });
+ }
+
+ /**
* Igore the request for now, the user may be prompted again.
*/
public void ignore() {
post(new Runnable() {
public void run() {
- mBrowserFrame.nativeSslClientCert(mHandle, null, null);
+ mBrowserFrame.nativeSslClientCert(mHandle, 0, null);
}
});
}
@@ -88,7 +115,7 @@ public final class ClientCertRequestHandler extends Handler {
mTable.Deny(mHostAndPort);
post(new Runnable() {
public void run() {
- mBrowserFrame.nativeSslClientCert(mHandle, null, null);
+ mBrowserFrame.nativeSslClientCert(mHandle, 0, null);
}
});
}
diff --git a/core/java/android/webkit/SslClientCertLookupTable.java b/core/java/android/webkit/SslClientCertLookupTable.java
index 630debd..c52b7e8 100644
--- a/core/java/android/webkit/SslClientCertLookupTable.java
+++ b/core/java/android/webkit/SslClientCertLookupTable.java
@@ -16,6 +16,7 @@
package android.webkit;
+import java.security.PrivateKey;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
@@ -26,7 +27,7 @@ import java.util.Set;
*/
final class SslClientCertLookupTable {
private static SslClientCertLookupTable sTable;
- private final Map<String, byte[]> privateKeys;
+ private final Map<String, PrivateKey> privateKeys;
private final Map<String, byte[][]> certificateChains;
private final Set<String> denied;
@@ -38,12 +39,12 @@ final class SslClientCertLookupTable {
}
private SslClientCertLookupTable() {
- privateKeys = new HashMap<String, byte[]>();
+ privateKeys = new HashMap<String, PrivateKey>();
certificateChains = new HashMap<String, byte[][]>();
denied = new HashSet<String>();
}
- public void Allow(String host_and_port, byte[] privateKey, byte[][] chain) {
+ public void Allow(String host_and_port, PrivateKey privateKey, byte[][] chain) {
privateKeys.put(host_and_port, privateKey);
certificateChains.put(host_and_port, chain);
denied.remove(host_and_port);
@@ -63,7 +64,7 @@ final class SslClientCertLookupTable {
return denied.contains(host_and_port);
}
- public byte[] PrivateKey(String host_and_port) {
+ public PrivateKey PrivateKey(String host_and_port) {
return privateKeys.get(host_and_port);
}
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index f0a9cc2..eb5f835 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -153,7 +153,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
@Override
public void onGlobalLayout() {
if (mWebView.isShown()) {
- setGLRectViewport();
+ setInvScreenRect();
}
}
}
@@ -162,7 +162,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
@Override
public void onScrollChanged() {
if (mWebView.isShown()) {
- setGLRectViewport();
+ setInvScreenRect();
}
}
}
@@ -644,8 +644,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private ZoomManager mZoomManager;
- private final Rect mGLRectViewport = new Rect();
- private final Rect mViewRectViewport = new Rect();
+ private final Rect mInvScreenRect = new Rect();
+ private final Rect mScreenRect = new Rect();
private final RectF mVisibleContentRect = new RectF();
private boolean mGLViewportEmpty = false;
WebViewInputConnection mInputConnection = null;
@@ -935,7 +935,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
private Paint mTouchCrossHairColor;
private int mTouchHighlightX;
private int mTouchHighlightY;
- private long mTouchHighlightRequested;
+ private boolean mShowTapHighlight;
// Basically this proxy is used to tell the Video to update layer tree at
// SetBaseLayer time and to pause when WebView paused.
@@ -4224,11 +4224,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
calcOurContentVisibleRectF(mVisibleContentRect);
if (canvas.isHardwareAccelerated()) {
- Rect glRectViewport = mGLViewportEmpty ? null : mGLRectViewport;
- Rect viewRectViewport = mGLViewportEmpty ? null : mViewRectViewport;
+ Rect invScreenRect = mGLViewportEmpty ? null : mInvScreenRect;
+ Rect screenRect = mGLViewportEmpty ? null : mScreenRect;
- int functor = nativeCreateDrawGLFunction(mNativeClass, glRectViewport,
- viewRectViewport, mVisibleContentRect, getScale(), extras);
+ int functor = nativeCreateDrawGLFunction(mNativeClass, invScreenRect,
+ screenRect, mVisibleContentRect, getScale(), extras);
((HardwareCanvas) canvas).callDrawGLFunction(functor);
if (mHardwareAccelSkia != getSettings().getHardwareAccelSkiaEnabled()) {
mHardwareAccelSkia = getSettings().getHardwareAccelSkiaEnabled();
@@ -4696,8 +4696,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
if (mInputConnection == null) {
mInputConnection = new WebViewInputConnection();
- mAutoCompletePopup = new AutoCompletePopup(mContext, this,
- mInputConnection);
+ mAutoCompletePopup = new AutoCompletePopup(this, mInputConnection);
}
mInputConnection.setupEditorInfo(outAttrs);
return mInputConnection;
@@ -5548,26 +5547,26 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
}
- void setGLRectViewport() {
+ void setInvScreenRect() {
// Use the getGlobalVisibleRect() to get the intersection among the parents
// visible == false means we're clipped - send a null rect down to indicate that
// we should not draw
- boolean visible = mWebView.getGlobalVisibleRect(mGLRectViewport);
+ boolean visible = mWebView.getGlobalVisibleRect(mInvScreenRect);
if (visible) {
// Then need to invert the Y axis, just for GL
View rootView = mWebView.getRootView();
int rootViewHeight = rootView.getHeight();
- mViewRectViewport.set(mGLRectViewport);
- int savedWebViewBottom = mGLRectViewport.bottom;
- mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeightImpl();
- mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
+ mScreenRect.set(mInvScreenRect);
+ int savedWebViewBottom = mInvScreenRect.bottom;
+ mInvScreenRect.bottom = rootViewHeight - mInvScreenRect.top - getVisibleTitleHeightImpl();
+ mInvScreenRect.top = rootViewHeight - savedWebViewBottom;
mGLViewportEmpty = false;
} else {
mGLViewportEmpty = true;
}
calcOurContentVisibleRectF(mVisibleContentRect);
- nativeUpdateDrawGLFunction(mNativeClass, mGLViewportEmpty ? null : mGLRectViewport,
- mGLViewportEmpty ? null : mViewRectViewport,
+ nativeUpdateDrawGLFunction(mNativeClass, mGLViewportEmpty ? null : mInvScreenRect,
+ mGLViewportEmpty ? null : mScreenRect,
mVisibleContentRect, getScale());
}
@@ -5583,7 +5582,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
// notify the WebKit about the new dimensions.
sendViewSizeZoom(false);
}
- setGLRectViewport();
+ setInvScreenRect();
return changed;
}
@@ -5754,6 +5753,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
if (mInputDispatcher.postPointerEvent(ev, getScrollX(),
getScrollY() - getTitleHeight(), mZoomManager.getInvScale())) {
+ mInputDispatcher.dispatchUiEvents();
return true;
} else {
Log.w(LOGTAG, "mInputDispatcher rejected the event!");
@@ -5827,8 +5827,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
data.mSlop = viewToContentDimension(mNavSlop);
removeTouchHighlight();
- if (!mBlockWebkitViewMessages) {
- mTouchHighlightRequested = SystemClock.uptimeMillis();
+ if (!mBlockWebkitViewMessages && mWebViewCore != null) {
mWebViewCore.sendMessageAtFrontOfQueue(
EventHub.HIT_TEST, data);
}
@@ -6023,10 +6022,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
if (deltaX * deltaX + deltaY * deltaY > mTouchSlopSquare) {
mHeldMotionless = MOTIONLESS_FALSE;
- nativeSetIsScrolling(true);
} else {
mHeldMotionless = MOTIONLESS_TRUE;
- nativeSetIsScrolling(false);
keepScrollBarsVisible = true;
}
@@ -7647,6 +7644,14 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
}
return isPressingHandle;
}
+
+ @Override
+ public void showTapHighlight(boolean show) {
+ if (mShowTapHighlight != show) {
+ mShowTapHighlight = show;
+ invalidate();
+ }
+ }
}
private void setHitTestTypeFromUrl(String url) {
@@ -7709,16 +7714,7 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
if (mFocusedNode.mHasFocus && mFocusedNode.mEditable) {
return false;
}
- long delay = SystemClock.uptimeMillis() - mTouchHighlightRequested;
- if (delay < ViewConfiguration.getTapTimeout()) {
- Rect r = mTouchHighlightRegion.getBounds();
- mWebView.postInvalidateDelayed(delay, r.left, r.top, r.right, r.bottom);
- return false;
- }
- if (mInputDispatcher == null) {
- return false;
- }
- return mInputDispatcher.shouldShowTapHighlight();
+ return mShowTapHighlight;
}
@@ -8245,6 +8241,12 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
@Override
public void run() {
+ if (mWebViewCore == null
+ || getWebView().getWindowToken() == null
+ || getWebView().getViewRootImpl() == null) {
+ // We've been detached and/or destroyed since this was posted
+ return;
+ }
final ListView listView = (ListView) LayoutInflater.from(mContext)
.inflate(com.android.internal.R.layout.select_dialog, null);
final MyArrayListAdapter adapter = new MyArrayListAdapter();
@@ -8604,11 +8606,11 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc
int color, int extra);
private native void nativeDumpDisplayTree(String urlOrNull);
private native boolean nativeEvaluateLayersAnimations(int nativeInstance);
- private native int nativeCreateDrawGLFunction(int nativeInstance, Rect rect,
- Rect viewRect, RectF visibleRect, float scale, int extras);
+ private native int nativeCreateDrawGLFunction(int nativeInstance, Rect invScreenRect,
+ Rect screenRect, RectF visibleContentRect, float scale, int extras);
private native int nativeGetDrawGLFunction(int nativeInstance);
- private native void nativeUpdateDrawGLFunction(int nativeInstance, Rect rect, Rect viewRect,
- RectF visibleRect, float scale);
+ private native void nativeUpdateDrawGLFunction(int nativeInstance, Rect invScreenRect,
+ Rect screenRect, RectF visibleContentRect, float scale);
private native String nativeGetSelection();
private native Rect nativeLayerBounds(int layer);
private native void nativeSetHeightCanMeasure(boolean measure);
diff --git a/core/java/android/webkit/WebViewInputDispatcher.java b/core/java/android/webkit/WebViewInputDispatcher.java
index ef23a11..9541435 100644
--- a/core/java/android/webkit/WebViewInputDispatcher.java
+++ b/core/java/android/webkit/WebViewInputDispatcher.java
@@ -99,6 +99,8 @@ final class WebViewInputDispatcher {
private boolean mPostDoNotSendTouchEventsToWebKitUntilNextGesture;
private boolean mPostLongPressScheduled;
private boolean mPostClickScheduled;
+ private boolean mPostShowTapHighlightScheduled;
+ private boolean mPostHideTapHighlightScheduled;
private int mPostLastWebKitXOffset;
private int mPostLastWebKitYOffset;
private float mPostLastWebKitScale;
@@ -133,6 +135,7 @@ final class WebViewInputDispatcher {
private static final int LONG_PRESS_TIMEOUT =
ViewConfiguration.getLongPressTimeout() + TAP_TIMEOUT;
private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
+ private static final int PRESSED_STATE_DURATION = ViewConfiguration.getPressedStateDuration();
/**
* Event type: Indicates a touch event type.
@@ -310,6 +313,7 @@ final class WebViewInputDispatcher {
}
unscheduleLongPressLocked();
unscheduleClickLocked();
+ hideTapCandidateLocked();
return false;
}
@@ -349,12 +353,6 @@ final class WebViewInputDispatcher {
}
}
- public boolean shouldShowTapHighlight() {
- synchronized (mLock) {
- return mPostLongPressScheduled || mPostClickScheduled;
- }
- }
-
private void postLongPress() {
synchronized (mLock) {
if (!mPostLongPressScheduled) {
@@ -385,6 +383,64 @@ final class WebViewInputDispatcher {
}
}
+ private void hideTapCandidateLocked() {
+ unscheduleHideTapHighlightLocked();
+ unscheduleShowTapHighlightLocked();
+ mUiCallbacks.showTapHighlight(false);
+ }
+
+ private void showTapCandidateLocked() {
+ unscheduleHideTapHighlightLocked();
+ unscheduleShowTapHighlightLocked();
+ mUiCallbacks.showTapHighlight(true);
+ scheduleHideTapHighlightLocked();
+ }
+
+ private void scheduleShowTapHighlightLocked() {
+ unscheduleShowTapHighlightLocked();
+ mPostShowTapHighlightScheduled = true;
+ mUiHandler.sendEmptyMessageDelayed(UiHandler.MSG_SHOW_TAP_HIGHLIGHT,
+ TAP_TIMEOUT);
+ }
+
+ private void unscheduleShowTapHighlightLocked() {
+ if (mPostShowTapHighlightScheduled) {
+ mPostShowTapHighlightScheduled = false;
+ mUiHandler.removeMessages(UiHandler.MSG_SHOW_TAP_HIGHLIGHT);
+ }
+ }
+
+ private void scheduleHideTapHighlightLocked() {
+ unscheduleHideTapHighlightLocked();
+ mPostHideTapHighlightScheduled = true;
+ mUiHandler.sendEmptyMessageDelayed(UiHandler.MSG_HIDE_TAP_HIGHLIGHT,
+ PRESSED_STATE_DURATION);
+ }
+
+ private void unscheduleHideTapHighlightLocked() {
+ if (mPostHideTapHighlightScheduled) {
+ mPostHideTapHighlightScheduled = false;
+ mUiHandler.removeMessages(UiHandler.MSG_HIDE_TAP_HIGHLIGHT);
+ }
+ }
+
+ private void postShowTapHighlight(boolean show) {
+ synchronized (mLock) {
+ if (show) {
+ if (!mPostShowTapHighlightScheduled) {
+ return;
+ }
+ mPostShowTapHighlightScheduled = false;
+ } else {
+ if (!mPostHideTapHighlightScheduled) {
+ return;
+ }
+ mPostHideTapHighlightScheduled = false;
+ }
+ mUiCallbacks.showTapHighlight(show);
+ }
+ }
+
private void scheduleClickLocked() {
unscheduleClickLocked();
mPostClickScheduled = true;
@@ -404,6 +460,7 @@ final class WebViewInputDispatcher {
return;
}
mPostClickScheduled = false;
+ showTapCandidateLocked();
MotionEvent event = mPostTouchStream.getLastEvent();
if (event == null || event.getAction() != MotionEvent.ACTION_UP) {
@@ -442,6 +499,7 @@ final class WebViewInputDispatcher {
private void enqueueDoubleTapLocked(MotionEvent event) {
unscheduleClickLocked();
+ hideTapCandidateLocked();
MotionEvent eventToEnqueue = MotionEvent.obtainNoHistory(event);
DispatchEvent d = obtainDispatchEventLocked(eventToEnqueue, EVENT_TYPE_DOUBLE_TAP, 0,
mPostLastWebKitXOffset, mPostLastWebKitYOffset, mPostLastWebKitScale);
@@ -458,6 +516,7 @@ final class WebViewInputDispatcher {
if ((deltaX * deltaX + deltaY * deltaY) > mTouchSlopSquared) {
unscheduleLongPressLocked();
mIsTapCandidate = false;
+ hideTapCandidateLocked();
}
}
@@ -474,14 +533,17 @@ final class WebViewInputDispatcher {
|| event.getPointerCount() > 1) {
unscheduleLongPressLocked();
unscheduleClickLocked();
+ hideTapCandidateLocked();
mIsDoubleTapCandidate = false;
mIsTapCandidate = false;
+ hideTapCandidateLocked();
} else if (action == MotionEvent.ACTION_DOWN) {
checkForDoubleTapOnDownLocked(event);
scheduleLongPressLocked();
mIsTapCandidate = true;
mInitialDownX = event.getX();
mInitialDownY = event.getY();
+ scheduleShowTapHighlightLocked();
} else if (action == MotionEvent.ACTION_UP) {
unscheduleLongPressLocked();
if (isClickCandidateLocked(event)) {
@@ -490,6 +552,8 @@ final class WebViewInputDispatcher {
} else {
scheduleClickLocked();
}
+ } else {
+ hideTapCandidateLocked();
}
} else if (action == MotionEvent.ACTION_MOVE) {
checkForSlopLocked(event);
@@ -959,6 +1023,12 @@ final class WebViewInputDispatcher {
* through webkit or false otherwise.
*/
public boolean shouldInterceptTouchEvent(MotionEvent event);
+
+ /**
+ * Inform's the UI that it should show the tap highlight
+ * @param show True if it should show the highlight, false if it should hide it
+ */
+ public void showTapHighlight(boolean show);
}
/* Implemented by {@link WebViewCore} to perform operations on the web kit thread. */
@@ -985,6 +1055,8 @@ final class WebViewInputDispatcher {
public static final int MSG_WEBKIT_TIMEOUT = 2;
public static final int MSG_LONG_PRESS = 3;
public static final int MSG_CLICK = 4;
+ public static final int MSG_SHOW_TAP_HIGHLIGHT = 5;
+ public static final int MSG_HIDE_TAP_HIGHLIGHT = 6;
public UiHandler(Looper looper) {
super(looper);
@@ -1005,6 +1077,12 @@ final class WebViewInputDispatcher {
case MSG_CLICK:
postClick();
break;
+ case MSG_SHOW_TAP_HIGHLIGHT:
+ postShowTapHighlight(true);
+ break;
+ case MSG_HIDE_TAP_HIGHLIGHT:
+ postShowTapHighlight(false);
+ break;
default:
throw new IllegalStateException("Unknown message type: " + msg.what);
}
diff --git a/core/java/android/widget/ActivityChooserModel.java b/core/java/android/widget/ActivityChooserModel.java
index c53b5f6..fba8d3a 100644
--- a/core/java/android/widget/ActivityChooserModel.java
+++ b/core/java/android/widget/ActivityChooserModel.java
@@ -761,6 +761,16 @@ public class ActivityChooserModel extends DataSetObservable {
}
/**
+ * Gets whether the given observer is already registered.
+ *
+ * @param observer The observer.
+ * @return True if already registered.
+ */
+ public boolean isRegisteredObserver(DataSetObserver observer) {
+ return mObservers.contains(observer);
+ }
+
+ /**
* Represents a record in the history.
*/
public final static class HistoricalRecord {
diff --git a/core/java/android/widget/ActivityChooserView.java b/core/java/android/widget/ActivityChooserView.java
index be6b4e2..0c0bb1e 100644
--- a/core/java/android/widget/ActivityChooserView.java
+++ b/core/java/android/widget/ActivityChooserView.java
@@ -20,8 +20,10 @@ import com.android.internal.R;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
@@ -174,6 +176,11 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
private int mDefaultActionButtonContentDescription;
/**
+ * Whether this view has a default activity affordance.
+ */
+ private boolean mHasDefaultActivity;
+
+ /**
* Create a new instance.
*
* @param context The application environment.
@@ -245,6 +252,8 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
Resources resources = context.getResources();
mListPopupMaxWidth = Math.max(resources.getDisplayMetrics().widthPixels / 2,
resources.getDimensionPixelSize(com.android.internal.R.dimen.config_prefDialogWidth));
+
+ updateHasDefaultActivity();
}
/**
@@ -258,6 +267,21 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
}
}
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ Configuration oldConfig = mContext.getResources().getConfiguration();
+ final int changed = oldConfig.diff(newConfig);
+ if ((changed & ActivityInfo.CONFIG_SCREEN_SIZE) != 0
+ || (changed & ActivityInfo.CONFIG_ORIENTATION) != 0) {
+ updateHasDefaultActivity();
+ }
+ }
+
+ private void updateHasDefaultActivity() {
+ mHasDefaultActivity = mContext.getResources().getBoolean(
+ R.bool.activity_chooser_view_has_default_activity);
+ }
+
/**
* Sets the background for the button that expands the activity
* overflow list.
@@ -383,7 +407,8 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
- if (dataModel != null) {
+ if (dataModel != null
+ && !dataModel.isRegisteredObserver(mModelDataSetOberver)) {
dataModel.registerObserver(mModelDataSetOberver);
}
mIsAttachedToWindow = true;
@@ -393,7 +418,8 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
ActivityChooserModel dataModel = mAdapter.getDataModel();
- if (dataModel != null) {
+ if (dataModel != null
+ && dataModel.isRegisteredObserver(mModelDataSetOberver)) {
dataModel.unregisterObserver(mModelDataSetOberver);
}
ViewTreeObserver viewTreeObserver = getViewTreeObserver();
@@ -496,7 +522,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
// Default activity button.
final int activityCount = mAdapter.getActivityCount();
final int historySize = mAdapter.getHistorySize();
- if (activityCount > 0 && historySize > 0) {
+ if (mHasDefaultActivity && activityCount > 0 && historySize > 0) {
mDefaultActivityButton.setVisibility(VISIBLE);
ResolveInfo activity = mAdapter.getDefaultActivity();
PackageManager packageManager = mContext.getPackageManager();
@@ -512,9 +538,9 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
}
// Activity chooser content.
if (mDefaultActivityButton.getVisibility() == VISIBLE) {
- mActivityChooserContent.setBackgroundDrawable(mActivityChooserContentBackground);
+ mActivityChooserContent.setBackground(mActivityChooserContentBackground);
} else {
- mActivityChooserContent.setBackgroundDrawable(null);
+ mActivityChooserContent.setBackground(null);
}
}
@@ -577,7 +603,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
// OnLongClickListener#onLongClick
@Override
public boolean onLongClick(View view) {
- if (view == mDefaultActivityButton) {
+ if (mHasDefaultActivity && view == mDefaultActivityButton) {
if (mAdapter.getCount() > 0) {
mIsSelectingDefaultActivity = true;
showPopupUnchecked(mInitialActivityCount);
@@ -630,14 +656,16 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
public void setDataModel(ActivityChooserModel dataModel) {
ActivityChooserModel oldDataModel = mAdapter.getDataModel();
- if (oldDataModel != null && isShown()) {
+ if (oldDataModel != null) {
oldDataModel.unregisterObserver(mModelDataSetOberver);
}
mDataModel = dataModel;
- if (dataModel != null && isShown()) {
+ if (dataModel != null) {
dataModel.registerObserver(mModelDataSetOberver);
+ notifyDataSetChanged();
+ } else {
+ notifyDataSetInvalidated();
}
- notifyDataSetChanged();
}
@Override
diff --git a/core/java/android/widget/AppSecurityPermissions.java b/core/java/android/widget/AppSecurityPermissions.java
index b409e26..64f6c07 100755
--- a/core/java/android/widget/AppSecurityPermissions.java
+++ b/core/java/android/widget/AppSecurityPermissions.java
@@ -18,7 +18,9 @@ package android.widget;
import com.android.internal.R;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -27,14 +29,13 @@ import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
-import android.text.Spannable;
-import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
+import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import java.text.Collator;
import java.util.ArrayList;
@@ -42,7 +43,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -58,16 +58,65 @@ import java.util.Set;
*
* {@hide}
*/
-public class AppSecurityPermissions implements View.OnClickListener {
+public class AppSecurityPermissions {
- private enum State {
- NO_PERMS,
- DANGEROUS_ONLY,
- NORMAL_ONLY,
- BOTH
+ public static final int WHICH_PERSONAL = 1<<0;
+ public static final int WHICH_DEVICE = 1<<1;
+ public static final int WHICH_NEW = 1<<2;
+ public static final int WHICH_ALL = 0xffff;
+
+ private final static String TAG = "AppSecurityPermissions";
+ private boolean localLOGV = false;
+ private Context mContext;
+ private LayoutInflater mInflater;
+ private PackageManager mPm;
+ private PackageInfo mInstalledPackageInfo;
+ private final Map<String, MyPermissionGroupInfo> mPermGroups
+ = new HashMap<String, MyPermissionGroupInfo>();
+ private final List<MyPermissionGroupInfo> mPermGroupsList
+ = new ArrayList<MyPermissionGroupInfo>();
+ private final PermissionGroupInfoComparator mPermGroupComparator;
+ private final PermissionInfoComparator mPermComparator;
+ private List<MyPermissionInfo> mPermsList;
+ private CharSequence mNewPermPrefix;
+ private Drawable mNormalIcon;
+ private Drawable mDangerousIcon;
+
+ static class MyPermissionGroupInfo extends PermissionGroupInfo {
+ CharSequence mLabel;
+
+ final ArrayList<MyPermissionInfo> mNewPermissions = new ArrayList<MyPermissionInfo>();
+ final ArrayList<MyPermissionInfo> mPersonalPermissions = new ArrayList<MyPermissionInfo>();
+ final ArrayList<MyPermissionInfo> mDevicePermissions = new ArrayList<MyPermissionInfo>();
+ final ArrayList<MyPermissionInfo> mAllPermissions = new ArrayList<MyPermissionInfo>();
+
+ MyPermissionGroupInfo(PermissionInfo perm) {
+ name = perm.packageName;
+ packageName = perm.packageName;
+ }
+
+ MyPermissionGroupInfo(PermissionGroupInfo info) {
+ super(info);
+ }
+
+ public Drawable loadGroupIcon(PackageManager pm) {
+ if (icon != 0) {
+ return loadIcon(pm);
+ } else {
+ ApplicationInfo appInfo;
+ try {
+ appInfo = pm.getApplicationInfo(packageName, 0);
+ return appInfo.loadIcon(pm);
+ } catch (NameNotFoundException e) {
+ }
+ }
+ return null;
+ }
}
static class MyPermissionInfo extends PermissionInfo {
+ CharSequence mLabel;
+
/**
* PackageInfo.requestedPermissionsFlags for the new package being installed.
*/
@@ -99,46 +148,108 @@ public class AppSecurityPermissions implements View.OnClickListener {
}
}
- private final static String TAG = "AppSecurityPermissions";
- private boolean localLOGV = false;
- private Context mContext;
- private LayoutInflater mInflater;
- private PackageManager mPm;
- private LinearLayout mPermsView;
- private Map<String, CharSequence> mNewMap;
- private Map<String, CharSequence> mDangerousMap;
- private Map<String, CharSequence> mNormalMap;
- private List<MyPermissionInfo> mPermsList;
- private String mDefaultGrpLabel;
- private String mDefaultGrpName="DefaultGrp";
- private String mPermFormat;
- private CharSequence mNewPermPrefix;
- private Drawable mNormalIcon;
- private Drawable mDangerousIcon;
- private boolean mExpanded;
- private Drawable mShowMaxIcon;
- private Drawable mShowMinIcon;
- private View mShowMore;
- private TextView mShowMoreText;
- private ImageView mShowMoreIcon;
- private State mCurrentState;
- private LinearLayout mNonDangerousList;
- private LinearLayout mDangerousList;
- private LinearLayout mNewList;
- private HashMap<String, CharSequence> mGroupLabelCache;
- private View mNoPermsView;
+ public static class PermissionItemView extends LinearLayout implements View.OnClickListener {
+ MyPermissionGroupInfo mGroup;
+ MyPermissionInfo mPerm;
+ AlertDialog mDialog;
+
+ public PermissionItemView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ setClickable(true);
+ }
+
+ public void setPermission(MyPermissionGroupInfo grp, MyPermissionInfo perm,
+ boolean first, CharSequence newPermPrefix) {
+ mGroup = grp;
+ mPerm = perm;
+
+ ImageView permGrpIcon = (ImageView) findViewById(R.id.perm_icon);
+ TextView permNameView = (TextView) findViewById(R.id.perm_name);
+
+ PackageManager pm = getContext().getPackageManager();
+ Drawable icon = null;
+ if (first) {
+ icon = grp.loadGroupIcon(pm);
+ }
+ CharSequence label = perm.mLabel;
+ if (perm.mNew && newPermPrefix != null) {
+ // If this is a new permission, format it appropriately.
+ SpannableStringBuilder builder = new SpannableStringBuilder();
+ Parcel parcel = Parcel.obtain();
+ TextUtils.writeToParcel(newPermPrefix, parcel, 0);
+ parcel.setDataPosition(0);
+ CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
+ parcel.recycle();
+ builder.append(newStr);
+ builder.append(label);
+ label = builder;
+ }
+
+ permGrpIcon.setImageDrawable(icon);
+ permNameView.setText(label);
+ setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ if (mGroup != null && mPerm != null) {
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ PackageManager pm = getContext().getPackageManager();
+ AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
+ builder.setTitle(mGroup.mLabel);
+ if (mPerm.descriptionRes != 0) {
+ builder.setMessage(mPerm.loadDescription(pm));
+ } else {
+ CharSequence appName;
+ try {
+ ApplicationInfo app = pm.getApplicationInfo(mPerm.packageName, 0);
+ appName = app.loadLabel(pm);
+ } catch (NameNotFoundException e) {
+ appName = mPerm.packageName;
+ }
+ StringBuilder sbuilder = new StringBuilder(128);
+ sbuilder.append(getContext().getString(
+ R.string.perms_description_app, appName));
+ sbuilder.append("\n\n");
+ sbuilder.append(mPerm.name);
+ builder.setMessage(sbuilder.toString());
+ }
+ builder.setCancelable(true);
+ builder.setIcon(mGroup.loadGroupIcon(pm));
+ mDialog = builder.show();
+ mDialog.setCanceledOnTouchOutside(true);
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
+ }
+ }
public AppSecurityPermissions(Context context, List<PermissionInfo> permList) {
mContext = context;
mPm = mContext.getPackageManager();
+ loadResources();
+ mPermComparator = new PermissionInfoComparator();
+ mPermGroupComparator = new PermissionGroupInfoComparator();
for (PermissionInfo pi : permList) {
mPermsList.add(new MyPermissionInfo(pi));
}
+ setPermissions(mPermsList);
}
public AppSecurityPermissions(Context context, String packageName) {
mContext = context;
mPm = mContext.getPackageManager();
+ loadResources();
+ mPermComparator = new PermissionInfoComparator();
+ mPermGroupComparator = new PermissionGroupInfoComparator();
mPermsList = new ArrayList<MyPermissionInfo>();
Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
PackageInfo pkgInfo;
@@ -155,11 +266,15 @@ public class AppSecurityPermissions implements View.OnClickListener {
for(MyPermissionInfo tmpInfo : permSet) {
mPermsList.add(tmpInfo);
}
+ setPermissions(mPermsList);
}
-
+
public AppSecurityPermissions(Context context, PackageParser.Package pkg) {
mContext = context;
mPm = mContext.getPackageManager();
+ loadResources();
+ mPermComparator = new PermissionInfoComparator();
+ mPermGroupComparator = new PermissionGroupInfoComparator();
mPermsList = new ArrayList<MyPermissionInfo>();
Set<MyPermissionInfo> permSet = new HashSet<MyPermissionInfo>();
if(pkg == null) {
@@ -193,10 +308,20 @@ public class AppSecurityPermissions implements View.OnClickListener {
for (MyPermissionInfo tmpInfo : permSet) {
mPermsList.add(tmpInfo);
}
+ setPermissions(mPermsList);
}
-
+
+ private void loadResources() {
+ // Pick up from framework resources instead.
+ mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
+ mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
+ mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
+ }
+
/**
- * Utility to retrieve a view displaying a single permission.
+ * Utility to retrieve a view displaying a single permission. This provides
+ * the old UI layout for permissions; it is only here for the device admin
+ * settings to continue to use.
*/
public static View getPermissionItemView(Context context,
CharSequence grpName, CharSequence description, boolean dangerous) {
@@ -204,10 +329,14 @@ public class AppSecurityPermissions implements View.OnClickListener {
Context.LAYOUT_INFLATER_SERVICE);
Drawable icon = context.getResources().getDrawable(dangerous
? R.drawable.ic_bullet_key_permission : R.drawable.ic_text_dot);
- return getPermissionItemView(context, inflater, grpName,
+ return getPermissionItemViewOld(context, inflater, grpName,
description, dangerous, icon);
}
+ public PackageInfo getInstalledPackageInfo() {
+ return mInstalledPackageInfo;
+ }
+
private void getAllUsedPermissions(int sharedUid, Set<MyPermissionInfo> permSet) {
String sharedPkgList[] = mPm.getPackagesForUid(sharedUid);
if(sharedPkgList == null || (sharedPkgList.length == 0)) {
@@ -239,6 +368,7 @@ public class AppSecurityPermissions implements View.OnClickListener {
if ((strList == null) || (strList.length == 0)) {
return;
}
+ mInstalledPackageInfo = installedPkgInfo;
for (int i=0; i<strList.length; i++) {
String permName = strList[i];
// If we are only looking at an existing app, then we only
@@ -270,13 +400,42 @@ public class AppSecurityPermissions implements View.OnClickListener {
// to see, so skip it.
continue;
}
+ final String origGroupName = tmpPermInfo.group;
+ String groupName = origGroupName;
+ if (groupName == null) {
+ groupName = tmpPermInfo.packageName;
+ tmpPermInfo.group = groupName;
+ }
+ MyPermissionGroupInfo group = mPermGroups.get(groupName);
+ if (group == null) {
+ PermissionGroupInfo grp = null;
+ if (origGroupName != null) {
+ grp = mPm.getPermissionGroupInfo(origGroupName, 0);
+ }
+ if (grp != null) {
+ group = new MyPermissionGroupInfo(grp);
+ } else {
+ // We could be here either because the permission
+ // didn't originally specify a group or the group it
+ // gave couldn't be found. In either case, we consider
+ // its group to be the permission's package name.
+ tmpPermInfo.group = tmpPermInfo.packageName;
+ group = mPermGroups.get(tmpPermInfo.group);
+ if (group == null) {
+ group = new MyPermissionGroupInfo(tmpPermInfo);
+ }
+ group = new MyPermissionGroupInfo(tmpPermInfo);
+ }
+ mPermGroups.put(tmpPermInfo.group, group);
+ }
+ final boolean newPerm = installedPkgInfo != null
+ && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
MyPermissionInfo myPerm = new MyPermissionInfo(tmpPermInfo);
myPerm.mNewReqFlags = flagsList[i];
myPerm.mExistingReqFlags = existingFlags;
// This is a new permission if the app is already installed and
// doesn't currently hold this permission.
- myPerm.mNew = installedPkgInfo != null
- && (existingFlags&PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0;
+ myPerm.mNew = newPerm;
permSet.add(myPerm);
} catch (NameNotFoundException e) {
Log.i(TAG, "Ignoring unknown permission:"+permName);
@@ -285,149 +444,99 @@ public class AppSecurityPermissions implements View.OnClickListener {
}
public int getPermissionCount() {
- return mPermsList.size();
+ return getPermissionCount(WHICH_ALL);
}
- public View getPermissionsView() {
-
- mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- mPermsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
- mShowMore = mPermsView.findViewById(R.id.show_more);
- mShowMoreIcon = (ImageView) mShowMore.findViewById(R.id.show_more_icon);
- mShowMoreText = (TextView) mShowMore.findViewById(R.id.show_more_text);
- mNewList = (LinearLayout) mPermsView.findViewById(R.id.new_perms_list);
- mDangerousList = (LinearLayout) mPermsView.findViewById(R.id.dangerous_perms_list);
- mNonDangerousList = (LinearLayout) mPermsView.findViewById(R.id.non_dangerous_perms_list);
- mNoPermsView = mPermsView.findViewById(R.id.no_permissions);
-
- // Set up the LinearLayout that acts like a list item.
- mShowMore.setClickable(true);
- mShowMore.setOnClickListener(this);
- mShowMore.setFocusable(true);
-
- // Pick up from framework resources instead.
- mDefaultGrpLabel = mContext.getString(R.string.default_permission_group);
- mPermFormat = mContext.getString(R.string.permissions_format);
- mNewPermPrefix = mContext.getText(R.string.perms_new_perm_prefix);
- mNormalIcon = mContext.getResources().getDrawable(R.drawable.ic_text_dot);
- mDangerousIcon = mContext.getResources().getDrawable(R.drawable.ic_bullet_key_permission);
- mShowMaxIcon = mContext.getResources().getDrawable(R.drawable.expander_close_holo_dark);
- mShowMinIcon = mContext.getResources().getDrawable(R.drawable.expander_open_holo_dark);
-
- // Set permissions view
- setPermissions(mPermsList);
- return mPermsView;
+ private List<MyPermissionInfo> getPermissionList(MyPermissionGroupInfo grp, int which) {
+ if (which == WHICH_NEW) {
+ return grp.mNewPermissions;
+ } else if (which == WHICH_PERSONAL) {
+ return grp.mPersonalPermissions;
+ } else if (which == WHICH_DEVICE) {
+ return grp.mDevicePermissions;
+ } else {
+ return grp.mAllPermissions;
+ }
}
- /**
- * Utility method that concatenates two strings defined by mPermFormat.
- * a null value is returned if both str1 and str2 are null, if one of the strings
- * is null the other non null value is returned without formatting
- * this is to placate initial error checks
- */
- private CharSequence formatPermissions(CharSequence groupDesc, CharSequence permDesc,
- boolean newPerms) {
- if (permDesc == null) {
- return groupDesc;
- }
- // Sometimes people write permission names with a trailing period;
- // strip that if it appears.
- int len = permDesc.length();
- if (len > 0 && permDesc.charAt(len-1) == '.') {
- permDesc = (permDesc.toString()).substring(0, len-1);
- }
- if (newPerms) {
- if (true) {
- // If this is a new permission, format it appropriately.
- SpannableStringBuilder builder = new SpannableStringBuilder();
- if (groupDesc != null) {
- // The previous permissions go in front, with a newline
- // separating them.
- builder.append(groupDesc);
- builder.append("\n");
- }
- Parcel parcel = Parcel.obtain();
- TextUtils.writeToParcel(mNewPermPrefix, parcel, 0);
- parcel.setDataPosition(0);
- CharSequence newStr = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(parcel);
- parcel.recycle();
- builder.append(newStr);
- builder.append(permDesc);
- return builder;
- } else {
- // If this is a new permission, format it appropriately.
- SpannableStringBuilder builder = new SpannableStringBuilder(permDesc);
- builder.insert(0, mNewPermPrefix);
- if (groupDesc != null) {
- // The previous permissions go in front, with a newline
- // separating them.
- builder.insert(0, "\n");
- builder.insert(0, groupDesc);
- }
- return builder;
- }
- }
- if (groupDesc == null) {
- return permDesc;
+ public int getPermissionCount(int which) {
+ int N = 0;
+ for (int i=0; i<mPermGroupsList.size(); i++) {
+ N += getPermissionList(mPermGroupsList.get(i), which).size();
}
- // groupDesc and permDesc are non null
- return String.format(mPermFormat, groupDesc, permDesc.toString());
+ return N;
}
- private CharSequence getGroupLabel(String grpName) {
- if (grpName == null) {
- //return default label
- return mDefaultGrpLabel;
- }
- CharSequence cachedLabel = mGroupLabelCache.get(grpName);
- if (cachedLabel != null) {
- return cachedLabel;
- }
- PermissionGroupInfo pgi;
- try {
- pgi = mPm.getPermissionGroupInfo(grpName, 0);
- } catch (NameNotFoundException e) {
- Log.i(TAG, "Invalid group name:" + grpName);
- return null;
+ public View getPermissionsView() {
+ return getPermissionsView(WHICH_ALL);
+ }
+
+ public View getPermissionsView(int which) {
+ mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+
+ LinearLayout permsView = (LinearLayout) mInflater.inflate(R.layout.app_perms_summary, null);
+ LinearLayout displayList = (LinearLayout) permsView.findViewById(R.id.perms_list);
+ View noPermsView = permsView.findViewById(R.id.no_permissions);
+
+ displayPermissions(mPermGroupsList, displayList, which);
+ if (displayList.getChildCount() <= 0) {
+ noPermsView.setVisibility(View.VISIBLE);
}
- CharSequence label = pgi.loadLabel(mPm).toString();
- mGroupLabelCache.put(grpName, label);
- return label;
+
+ return permsView;
}
/**
* Utility method that displays permissions from a map containing group name and
* list of permission descriptions.
*/
- private void displayPermissions(Map<String, CharSequence> permInfoMap,
- LinearLayout permListView, boolean dangerous) {
+ private void displayPermissions(List<MyPermissionGroupInfo> groups,
+ LinearLayout permListView, int which) {
permListView.removeAllViews();
- Set<String> permInfoStrSet = permInfoMap.keySet();
- for (String loopPermGrpInfoStr : permInfoStrSet) {
- CharSequence grpLabel = getGroupLabel(loopPermGrpInfoStr);
- //guaranteed that grpLabel wont be null since permissions without groups
- //will belong to the default group
- if(localLOGV) Log.i(TAG, "Adding view group:" + grpLabel + ", desc:"
- + permInfoMap.get(loopPermGrpInfoStr));
- permListView.addView(getPermissionItemView(grpLabel,
- permInfoMap.get(loopPermGrpInfoStr), dangerous));
+ int spacing = (int)(8*mContext.getResources().getDisplayMetrics().density);
+
+ for (int i=0; i<groups.size(); i++) {
+ MyPermissionGroupInfo grp = groups.get(i);
+ final List<MyPermissionInfo> perms = getPermissionList(grp, which);
+ for (int j=0; j<perms.size(); j++) {
+ MyPermissionInfo perm = perms.get(j);
+ View view = getPermissionItemView(grp, perm, j == 0,
+ which != WHICH_NEW ? mNewPermPrefix : null);
+ LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT);
+ if (j == 0) {
+ lp.topMargin = spacing;
+ }
+ if (j == grp.mAllPermissions.size()-1) {
+ lp.bottomMargin = spacing;
+ }
+ if (permListView.getChildCount() == 0) {
+ lp.topMargin *= 2;
+ }
+ permListView.addView(view, lp);
+ }
}
}
- private void displayNoPermissions() {
- mNoPermsView.setVisibility(View.VISIBLE);
+ private PermissionItemView getPermissionItemView(MyPermissionGroupInfo grp,
+ MyPermissionInfo perm, boolean first, CharSequence newPermPrefix) {
+ return getPermissionItemView(mContext, mInflater, grp, perm, first, newPermPrefix);
}
- private View getPermissionItemView(CharSequence grpName, CharSequence permList,
- boolean dangerous) {
- return getPermissionItemView(mContext, mInflater, grpName, permList,
- dangerous, dangerous ? mDangerousIcon : mNormalIcon);
+ private static PermissionItemView getPermissionItemView(Context context, LayoutInflater inflater,
+ MyPermissionGroupInfo grp, MyPermissionInfo perm, boolean first,
+ CharSequence newPermPrefix) {
+ PermissionItemView permView = (PermissionItemView)inflater.inflate(
+ R.layout.app_permission_item, null);
+ permView.setPermission(grp, perm, first, newPermPrefix);
+ return permView;
}
- private static View getPermissionItemView(Context context, LayoutInflater inflater,
+ private static View getPermissionItemViewOld(Context context, LayoutInflater inflater,
CharSequence grpName, CharSequence permList, boolean dangerous, Drawable icon) {
- View permView = inflater.inflate(R.layout.app_permission_item, null);
+ View permView = inflater.inflate(R.layout.app_permission_item_old, null);
TextView permGrpView = (TextView) permView.findViewById(R.id.permission_group);
TextView permDescView = (TextView) permView.findViewById(R.id.permission_list);
@@ -444,41 +553,6 @@ public class AppSecurityPermissions implements View.OnClickListener {
return permView;
}
- private void showPermissions() {
-
- switch(mCurrentState) {
- case NO_PERMS:
- displayNoPermissions();
- break;
-
- case DANGEROUS_ONLY:
- displayPermissions(mNewMap, mNewList, true);
- displayPermissions(mDangerousMap, mDangerousList, true);
- break;
-
- case NORMAL_ONLY:
- displayPermissions(mNewMap, mNewList, true);
- displayPermissions(mNormalMap, mNonDangerousList, false);
- break;
-
- case BOTH:
- displayPermissions(mNewMap, mNewList, true);
- displayPermissions(mDangerousMap, mDangerousList, true);
- if (mExpanded) {
- displayPermissions(mNormalMap, mNonDangerousList, false);
- mShowMoreIcon.setImageDrawable(mShowMaxIcon);
- mShowMoreText.setText(R.string.perms_hide);
- mNonDangerousList.setVisibility(View.VISIBLE);
- } else {
- mShowMoreIcon.setImageDrawable(mShowMinIcon);
- mShowMoreText.setText(R.string.perms_show_all);
- mNonDangerousList.setVisibility(View.GONE);
- }
- mShowMore.setVisibility(View.VISIBLE);
- break;
- }
- }
-
private boolean isDisplayablePermission(PermissionInfo pInfo, int newReqFlags,
int existingReqFlags) {
final int base = pInfo.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
@@ -496,79 +570,45 @@ public class AppSecurityPermissions implements View.OnClickListener {
}
return false;
}
-
- /*
- * Utility method that aggregates all permission descriptions categorized by group
- * Say group1 has perm11, perm12, perm13, the group description will be
- * perm11_Desc, perm12_Desc, perm13_Desc
- */
- private void aggregateGroupDescs(Map<String, List<MyPermissionInfo> > map,
- Map<String, CharSequence> retMap, boolean newPerms) {
- if(map == null) {
- return;
+
+ private static class PermissionGroupInfoComparator implements Comparator<MyPermissionGroupInfo> {
+ private final Collator sCollator = Collator.getInstance();
+ PermissionGroupInfoComparator() {
}
- if(retMap == null) {
- return;
- }
- Set<String> grpNames = map.keySet();
- Iterator<String> grpNamesIter = grpNames.iterator();
- while(grpNamesIter.hasNext()) {
- CharSequence grpDesc = null;
- String grpNameKey = grpNamesIter.next();
- List<MyPermissionInfo> grpPermsList = map.get(grpNameKey);
- if(grpPermsList == null) {
- continue;
- }
- for(PermissionInfo permInfo: grpPermsList) {
- CharSequence permDesc = permInfo.loadLabel(mPm);
- grpDesc = formatPermissions(grpDesc, permDesc, newPerms);
+ public final int compare(MyPermissionGroupInfo a, MyPermissionGroupInfo b) {
+ if (((a.flags^b.flags)&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
+ return ((a.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) ? -1 : 1;
}
- // Insert grpDesc into map
- if(grpDesc != null) {
- if(localLOGV) Log.i(TAG, "Group:"+grpNameKey+" description:"+grpDesc.toString());
- retMap.put(grpNameKey, grpDesc);
+ if (a.priority != b.priority) {
+ return a.priority > b.priority ? -1 : 1;
}
+ return sCollator.compare(a.mLabel, b.mLabel);
}
}
- private static class PermissionInfoComparator implements Comparator<PermissionInfo> {
- private PackageManager mPm;
+ private static class PermissionInfoComparator implements Comparator<MyPermissionInfo> {
private final Collator sCollator = Collator.getInstance();
- PermissionInfoComparator(PackageManager pm) {
- mPm = pm;
+ PermissionInfoComparator() {
}
- public final int compare(PermissionInfo a, PermissionInfo b) {
- CharSequence sa = a.loadLabel(mPm);
- CharSequence sb = b.loadLabel(mPm);
- return sCollator.compare(sa, sb);
+ public final int compare(MyPermissionInfo a, MyPermissionInfo b) {
+ return sCollator.compare(a.mLabel, b.mLabel);
}
}
-
+
+ private void addPermToList(List<MyPermissionInfo> permList,
+ MyPermissionInfo pInfo) {
+ if (pInfo.mLabel == null) {
+ pInfo.mLabel = pInfo.loadLabel(mPm);
+ }
+ int idx = Collections.binarySearch(permList, pInfo, mPermComparator);
+ if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+permList.size());
+ if (idx < 0) {
+ idx = -idx-1;
+ permList.add(idx, pInfo);
+ }
+ }
+
private void setPermissions(List<MyPermissionInfo> permList) {
- mGroupLabelCache = new HashMap<String, CharSequence>();
- //add the default label so that uncategorized permissions can go here
- mGroupLabelCache.put(mDefaultGrpName, mDefaultGrpLabel);
-
- // Map containing group names and a list of permissions under that group
- // that are new from the current install
- mNewMap = new HashMap<String, CharSequence>();
- // Map containing group names and a list of permissions under that group
- // categorized as dangerous
- mDangerousMap = new HashMap<String, CharSequence>();
- // Map containing group names and a list of permissions under that group
- // categorized as normal
- mNormalMap = new HashMap<String, CharSequence>();
-
- // Additional structures needed to ensure that permissions are unique under
- // each group
- Map<String, List<MyPermissionInfo>> newMap =
- new HashMap<String, List<MyPermissionInfo>>();
- Map<String, List<MyPermissionInfo>> dangerousMap =
- new HashMap<String, List<MyPermissionInfo>>();
- Map<String, List<MyPermissionInfo> > normalMap =
- new HashMap<String, List<MyPermissionInfo>>();
- PermissionInfoComparator permComparator = new PermissionInfoComparator(mPm);
-
if (permList != null) {
// First pass to group permissions
for (MyPermissionInfo pInfo : permList) {
@@ -577,51 +617,43 @@ public class AppSecurityPermissions implements View.OnClickListener {
if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" is not displayable");
continue;
}
- Map<String, List<MyPermissionInfo> > permInfoMap;
- if (pInfo.mNew) {
- permInfoMap = newMap;
- } else if ((pInfo.protectionLevel&PermissionInfo.PROTECTION_MASK_BASE)
- == PermissionInfo.PROTECTION_DANGEROUS) {
- permInfoMap = dangerousMap;
- } else {
- permInfoMap = normalMap;
- }
- String grpName = (pInfo.group == null) ? mDefaultGrpName : pInfo.group;
- if(localLOGV) Log.i(TAG, "Permission:"+pInfo.name+" belongs to group:"+grpName);
- List<MyPermissionInfo> grpPermsList = permInfoMap.get(grpName);
- if(grpPermsList == null) {
- grpPermsList = new ArrayList<MyPermissionInfo>();
- permInfoMap.put(grpName, grpPermsList);
- grpPermsList.add(pInfo);
- } else {
- int idx = Collections.binarySearch(grpPermsList, pInfo, permComparator);
- if(localLOGV) Log.i(TAG, "idx="+idx+", list.size="+grpPermsList.size());
- if (idx < 0) {
- idx = -idx-1;
- grpPermsList.add(idx, pInfo);
+ MyPermissionGroupInfo group = mPermGroups.get(pInfo.group);
+ if (group != null) {
+ pInfo.mLabel = pInfo.loadLabel(mPm);
+ addPermToList(group.mAllPermissions, pInfo);
+ if (pInfo.mNew) {
+ addPermToList(group.mNewPermissions, pInfo);
+ }
+ if ((group.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0) {
+ addPermToList(group.mPersonalPermissions, pInfo);
+ } else {
+ addPermToList(group.mDevicePermissions, pInfo);
}
}
}
- // Second pass to actually form the descriptions
- // Look at dangerous permissions first
- aggregateGroupDescs(newMap, mNewMap, true);
- aggregateGroupDescs(dangerousMap, mDangerousMap, false);
- aggregateGroupDescs(normalMap, mNormalMap, false);
}
- mCurrentState = State.NO_PERMS;
- if (mNewMap.size() > 0 || mDangerousMap.size() > 0) {
- mCurrentState = (mNormalMap.size() > 0) ? State.BOTH : State.DANGEROUS_ONLY;
- } else if(mNormalMap.size() > 0) {
- mCurrentState = State.NORMAL_ONLY;
+ for (MyPermissionGroupInfo pgrp : mPermGroups.values()) {
+ if (pgrp.labelRes != 0 || pgrp.nonLocalizedLabel != null) {
+ pgrp.mLabel = pgrp.loadLabel(mPm);
+ } else {
+ ApplicationInfo app;
+ try {
+ app = mPm.getApplicationInfo(pgrp.packageName, 0);
+ pgrp.mLabel = app.loadLabel(mPm);
+ } catch (NameNotFoundException e) {
+ pgrp.mLabel = pgrp.loadLabel(mPm);
+ }
+ }
+ mPermGroupsList.add(pgrp);
+ }
+ Collections.sort(mPermGroupsList, mPermGroupComparator);
+ if (false) {
+ for (MyPermissionGroupInfo grp : mPermGroupsList) {
+ Log.i("foo", "Group " + grp.name + " personal="
+ + ((grp.flags&PermissionGroupInfo.FLAG_PERSONAL_INFO) != 0)
+ + " priority=" + grp.priority);
+ }
}
- if(localLOGV) Log.i(TAG, "mCurrentState=" + mCurrentState);
- showPermissions();
- }
-
- public void onClick(View v) {
- if(localLOGV) Log.i(TAG, "mExpanded="+mExpanded);
- mExpanded = !mExpanded;
- showPermissions();
}
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 2a74f6a..b06da06 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -421,6 +421,8 @@ public class CalendarView extends FrameLayout {
* Sets the number of weeks to be shown.
*
* @param count The shown week count.
+ *
+ * @attr ref android.R.styleable#CalendarView_shownWeekCount
*/
public void setShownWeekCount(int count) {
if (mShownWeekCount != count) {
@@ -433,6 +435,8 @@ public class CalendarView extends FrameLayout {
* Gets the number of weeks to be shown.
*
* @return The shown week count.
+ *
+ * @attr ref android.R.styleable#CalendarView_shownWeekCount
*/
public int getShownWeekCount() {
return mShownWeekCount;
@@ -442,6 +446,8 @@ public class CalendarView extends FrameLayout {
* Sets the background color for the selected week.
*
* @param color The week background color.
+ *
+ * @attr ref android.R.styleable#CalendarView_selectedWeekBackgroundColor
*/
public void setSelectedWeekBackgroundColor(int color) {
if (mSelectedWeekBackgroundColor != color) {
@@ -460,6 +466,8 @@ public class CalendarView extends FrameLayout {
* Gets the background color for the selected week.
*
* @return The week background color.
+ *
+ * @attr ref android.R.styleable#CalendarView_selectedWeekBackgroundColor
*/
public int getSelectedWeekBackgroundColor() {
return mSelectedWeekBackgroundColor;
@@ -469,6 +477,8 @@ public class CalendarView extends FrameLayout {
* Sets the color for the dates of the focused month.
*
* @param color The focused month date color.
+ *
+ * @attr ref android.R.styleable#CalendarView_focusedMonthDateColor
*/
public void setFocusedMonthDateColor(int color) {
if (mFocusedMonthDateColor != color) {
@@ -487,6 +497,8 @@ public class CalendarView extends FrameLayout {
* Gets the color for the dates in the focused month.
*
* @return The focused month date color.
+ *
+ * @attr ref android.R.styleable#CalendarView_focusedMonthDateColor
*/
public int getFocusedMonthDateColor() {
return mFocusedMonthDateColor;
@@ -496,6 +508,8 @@ public class CalendarView extends FrameLayout {
* Sets the color for the dates of a not focused month.
*
* @param color A not focused month date color.
+ *
+ * @attr ref android.R.styleable#CalendarView_unfocusedMonthDateColor
*/
public void setUnfocusedMonthDateColor(int color) {
if (mUnfocusedMonthDateColor != color) {
@@ -514,6 +528,8 @@ public class CalendarView extends FrameLayout {
* Gets the color for the dates in a not focused month.
*
* @return A not focused month date color.
+ *
+ * @attr ref android.R.styleable#CalendarView_unfocusedMonthDateColor
*/
public int getUnfocusedMonthDateColor() {
return mFocusedMonthDateColor;
@@ -523,6 +539,8 @@ public class CalendarView extends FrameLayout {
* Sets the color for the week numbers.
*
* @param color The week number color.
+ *
+ * @attr ref android.R.styleable#CalendarView_weekNumberColor
*/
public void setWeekNumberColor(int color) {
if (mWeekNumberColor != color) {
@@ -537,6 +555,8 @@ public class CalendarView extends FrameLayout {
* Gets the color for the week numbers.
*
* @return The week number color.
+ *
+ * @attr ref android.R.styleable#CalendarView_weekNumberColor
*/
public int getWeekNumberColor() {
return mWeekNumberColor;
@@ -546,6 +566,8 @@ public class CalendarView extends FrameLayout {
* Sets the color for the separator line between weeks.
*
* @param color The week separator color.
+ *
+ * @attr ref android.R.styleable#CalendarView_weekSeparatorLineColor
*/
public void setWeekSeparatorLineColor(int color) {
if (mWeekSeparatorLineColor != color) {
@@ -558,6 +580,8 @@ public class CalendarView extends FrameLayout {
* Gets the color for the separator line between weeks.
*
* @return The week separator color.
+ *
+ * @attr ref android.R.styleable#CalendarView_weekSeparatorLineColor
*/
public int getWeekSeparatorLineColor() {
return mWeekSeparatorLineColor;
@@ -568,6 +592,8 @@ public class CalendarView extends FrameLayout {
* the end of the selected date.
*
* @param resourceId The vertical bar drawable resource id.
+ *
+ * @attr ref android.R.styleable#CalendarView_selectedDateVerticalBar
*/
public void setSelectedDateVerticalBar(int resourceId) {
Drawable drawable = getResources().getDrawable(resourceId);
@@ -579,6 +605,8 @@ public class CalendarView extends FrameLayout {
* the end of the selected date.
*
* @param drawable The vertical bar drawable.
+ *
+ * @attr ref android.R.styleable#CalendarView_selectedDateVerticalBar
*/
public void setSelectedDateVerticalBar(Drawable drawable) {
if (mSelectedDateVerticalBar != drawable) {
@@ -607,6 +635,8 @@ public class CalendarView extends FrameLayout {
* Sets the text appearance for the week day abbreviation of the calendar header.
*
* @param resourceId The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#CalendarView_weekDayTextAppearance
*/
public void setWeekDayTextAppearance(int resourceId) {
if (mWeekDayTextAppearanceResId != resourceId) {
@@ -619,6 +649,8 @@ public class CalendarView extends FrameLayout {
* Gets the text appearance for the week day abbreviation of the calendar header.
*
* @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#CalendarView_weekDayTextAppearance
*/
public int getWeekDayTextAppearance() {
return mWeekDayTextAppearanceResId;
@@ -628,6 +660,8 @@ public class CalendarView extends FrameLayout {
* Sets the text appearance for the calendar dates.
*
* @param resourceId The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#CalendarView_dateTextAppearance
*/
public void setDateTextAppearance(int resourceId) {
if (mDateTextAppearanceResId != resourceId) {
@@ -641,6 +675,8 @@ public class CalendarView extends FrameLayout {
* Gets the text appearance for the calendar dates.
*
* @return The text appearance resource id.
+ *
+ * @attr ref android.R.styleable#CalendarView_dateTextAppearance
*/
public int getDateTextAppearance() {
return mDateTextAppearanceResId;
@@ -683,6 +719,8 @@ public class CalendarView extends FrameLayout {
* <p>
*
* @return The minimal supported date.
+ *
+ * @attr ref android.R.styleable#CalendarView_minDate
*/
public long getMinDate() {
return mMinDate.getTimeInMillis();
@@ -694,6 +732,8 @@ public class CalendarView extends FrameLayout {
* zone.
*
* @param minDate The minimal supported date.
+ *
+ * @attr ref android.R.styleable#CalendarView_minDate
*/
public void setMinDate(long minDate) {
mTempDate.setTimeInMillis(minDate);
@@ -731,6 +771,8 @@ public class CalendarView extends FrameLayout {
* <p>
*
* @return The maximal supported date.
+ *
+ * @attr ref android.R.styleable#CalendarView_maxDate
*/
public long getMaxDate() {
return mMaxDate.getTimeInMillis();
@@ -742,6 +784,8 @@ public class CalendarView extends FrameLayout {
* zone.
*
* @param maxDate The maximal supported date.
+ *
+ * @attr ref android.R.styleable#CalendarView_maxDate
*/
public void setMaxDate(long maxDate) {
mTempDate.setTimeInMillis(maxDate);
@@ -767,6 +811,8 @@ public class CalendarView extends FrameLayout {
* Sets whether to show the week number.
*
* @param showWeekNumber True to show the week number.
+ *
+ * @attr ref android.R.styleable#CalendarView_showWeekNumber
*/
public void setShowWeekNumber(boolean showWeekNumber) {
if (mShowWeekNumber == showWeekNumber) {
@@ -781,6 +827,8 @@ public class CalendarView extends FrameLayout {
* Gets whether to show the week number.
*
* @return True if showing the week number.
+ *
+ * @attr ref android.R.styleable#CalendarView_showWeekNumber
*/
public boolean getShowWeekNumber() {
return mShowWeekNumber;
@@ -798,6 +846,8 @@ public class CalendarView extends FrameLayout {
* @see Calendar#FRIDAY
* @see Calendar#SATURDAY
* @see Calendar#SUNDAY
+ *
+ * @attr ref android.R.styleable#CalendarView_firstDayOfWeek
*/
public int getFirstDayOfWeek() {
return mFirstDayOfWeek;
@@ -815,6 +865,8 @@ public class CalendarView extends FrameLayout {
* @see Calendar#FRIDAY
* @see Calendar#SATURDAY
* @see Calendar#SUNDAY
+ *
+ * @attr ref android.R.styleable#CalendarView_firstDayOfWeek
*/
public void setFirstDayOfWeek(int firstDayOfWeek) {
if (mFirstDayOfWeek == firstDayOfWeek) {
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 7593bff..cf28da4 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -193,6 +193,9 @@ public class ImageView extends View {
}
}
+ /**
+ * @hide
+ */
@Override
public int getResolvedLayoutDirection(Drawable dr) {
return (dr == mDrawable) ?
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 5ed005f..2391898 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -867,7 +867,7 @@ public class LinearLayout extends ViewGroup {
// We have no limit, so make all weighted views as tall as the largest child.
// Children will have already been measured once.
- if (useLargestChild && widthMode == MeasureSpec.UNSPECIFIED) {
+ if (useLargestChild && heightMode != MeasureSpec.EXACTLY) {
for (int i = 0; i < count; i++) {
final View child = getVirtualChildAt(i);
@@ -1283,7 +1283,7 @@ public class LinearLayout extends ViewGroup {
// We have no limit, so make all weighted views as wide as the largest child.
// Children will have already been measured once.
- if (useLargestChild && widthMode == MeasureSpec.UNSPECIFIED) {
+ if (useLargestChild && widthMode != MeasureSpec.EXACTLY) {
for (int i = 0; i < count; i++) {
final View child = getVirtualChildAt(i);
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 0b49404..f3f18d5 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -211,6 +211,7 @@ public class ProgressBar extends View {
private boolean mOnlyIndeterminate;
private Transformation mTransformation;
private AlphaAnimation mAnimation;
+ private boolean mHasAnimation;
private Drawable mIndeterminateDrawable;
private Drawable mProgressDrawable;
private Drawable mCurrentDrawable;
@@ -670,18 +671,14 @@ public class ProgressBar extends View {
if (mUiThreadId == Thread.currentThread().getId()) {
doRefreshProgress(id, progress, fromUser, true);
} else {
- RefreshProgressRunnable r;
- if (mRefreshProgressRunnable != null) {
- // Use cached RefreshProgressRunnable if available
- r = mRefreshProgressRunnable;
- } else {
- // Make a new one
- r = new RefreshProgressRunnable();
+ if (mRefreshProgressRunnable == null) {
+ mRefreshProgressRunnable = new RefreshProgressRunnable();
}
+
final RefreshData rd = RefreshData.obtain(id, progress, fromUser);
mRefreshData.add(rd);
if (mAttached && !mRefreshIsPosted) {
- post(r);
+ post(mRefreshProgressRunnable);
mRefreshIsPosted = true;
}
}
@@ -860,14 +857,26 @@ public class ProgressBar extends View {
if (mIndeterminateDrawable instanceof Animatable) {
mShouldStartAnimationDrawable = true;
- mAnimation = null;
+ mHasAnimation = false;
} else {
+ mHasAnimation = true;
+
if (mInterpolator == null) {
mInterpolator = new LinearInterpolator();
}
- mTransformation = new Transformation();
- mAnimation = new AlphaAnimation(0.0f, 1.0f);
+ if (mTransformation == null) {
+ mTransformation = new Transformation();
+ } else {
+ mTransformation.clear();
+ }
+
+ if (mAnimation == null) {
+ mAnimation = new AlphaAnimation(0.0f, 1.0f);
+ } else {
+ mAnimation.reset();
+ }
+
mAnimation.setRepeatMode(mBehavior);
mAnimation.setRepeatCount(Animation.INFINITE);
mAnimation.setDuration(mDuration);
@@ -881,8 +890,7 @@ public class ProgressBar extends View {
* <p>Stop the indeterminate progress animation.</p>
*/
void stopAnimation() {
- mAnimation = null;
- mTransformation = null;
+ mHasAnimation = false;
if (mIndeterminateDrawable instanceof Animatable) {
((Animatable) mIndeterminateDrawable).stop();
mShouldStartAnimationDrawable = false;
@@ -967,6 +975,9 @@ public class ProgressBar extends View {
}
}
+ /**
+ * @hide
+ */
@Override
public int getResolvedLayoutDirection(Drawable who) {
return (who == mProgressDrawable || who == mIndeterminateDrawable) ?
@@ -1027,7 +1038,7 @@ public class ProgressBar extends View {
canvas.save();
canvas.translate(mPaddingLeft, mPaddingTop);
long time = getDrawingTime();
- if (mAnimation != null) {
+ if (mHasAnimation) {
mAnimation.getTransformation(time, mTransformation);
float scale = mTransformation.getAlpha();
try {
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index d8c23a1..56c4bd8 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -1556,15 +1556,13 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
- * Equivalent to calling {@link
- * TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}.
- *
* @param viewId The id of the view whose text should change
- * @param start The id of a drawable to place before the text (relative to the
+ * @param start The id of a drawable to place before the text (relative to the
* layout direction), or 0
* @param top The id of a drawable to place above the text, or 0
* @param end The id of a drawable to place after the text, or 0
- * @param bottom The id of a drawable to place below the text, or 0
+ * @param bottom The id of a drawable to place below the text, or 0
+ * @hide
*/
public void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom) {
addAction(new TextViewDrawableAction(viewId, true, start, top, end, bottom));
diff --git a/core/java/android/widget/SearchView.java b/core/java/android/widget/SearchView.java
index 561326e..521597b 100644
--- a/core/java/android/widget/SearchView.java
+++ b/core/java/android/widget/SearchView.java
@@ -576,6 +576,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
/**
* Returns the default iconified state of the search field.
* @return
+ *
+ * @attr ref android.R.styleable#SearchView_iconifiedByDefault
*/
public boolean isIconfiedByDefault() {
return mIconifiedByDefault;
@@ -696,6 +698,8 @@ public class SearchView extends LinearLayout implements CollapsibleActionView {
* Gets the specified maximum width in pixels, if set. Returns zero if
* no maximum width was specified.
* @return the maximum width of the view
+ *
+ * @attr ref android.R.styleable#SearchView_maxWidth
*/
public int getMaxWidth() {
return mMaxWidth;
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 080b87d..367561e 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -44,6 +44,7 @@ import com.android.internal.R;
* <code>
* // In Activity#onCreateOptionsMenu
* public boolean onCreateOptionsMenu(Menu menu) {
+ * getManuInflater().inflate(R.menu.my_menu, menu);
* // Get the menu item.
* MenuItem menuItem = menu.findItem(R.id.my_menu_item);
* // Get the provider and hold onto it to set/change the share intent.
@@ -239,7 +240,11 @@ public class ShareActionProvider extends ActionProvider {
* <p>
* <strong>Note:</strong> The history file name can be set any time, however
* only the action views created by {@link #onCreateActionView()} after setting
- * the file name will be backed by the provided file.
+ * the file name will be backed by the provided file. Hence, if you are using
+ * a share action provider on a menu item and want to change the history file
+ * based on the type of the currently selected item, you need to call
+ * {@link android.app.Activity#invalidateOptionsMenu()} to force the system
+ * to recreate the menu UI.
* <p>
*
* @param shareHistoryFile The share history file name.
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index 98e45fb..e1103dd 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -21,10 +21,12 @@ import android.text.Editable;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
+import android.text.TextUtils;
import android.text.method.WordIterator;
import android.text.style.SpellCheckSpan;
import android.text.style.SuggestionSpan;
import android.util.Log;
+import android.util.LruCache;
import android.view.textservice.SentenceSuggestionsInfo;
import android.view.textservice.SpellCheckerSession;
import android.view.textservice.SpellCheckerSession.SpellCheckerSessionListener;
@@ -95,6 +97,10 @@ public class SpellChecker implements SpellCheckerSessionListener {
private Runnable mSpellRunnable;
+ private static final int SUGGESTION_SPAN_CACHE_SIZE = 10;
+ private final LruCache<Long, SuggestionSpan> mSuggestionSpanCache =
+ new LruCache<Long, SuggestionSpan>(SUGGESTION_SPAN_CACHE_SIZE);
+
public SpellChecker(TextView textView) {
mTextView = textView;
@@ -126,6 +132,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
// Restore SpellCheckSpans in pool
for (int i = 0; i < mLength; i++) {
+ // Resets id and progress to invalidate spell check span
mSpellCheckSpans[i].setSpellCheckInProgress(false);
mIds[i] = -1;
}
@@ -133,6 +140,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
// Remove existing misspelled SuggestionSpans
mTextView.removeMisspelledSpans((Editable) mTextView.getText());
+ mSuggestionSpanCache.evictAll();
}
private void setLocale(Locale locale) {
@@ -199,6 +207,7 @@ public class SpellChecker implements SpellCheckerSessionListener {
public void removeSpellCheckSpan(SpellCheckSpan spellCheckSpan) {
for (int i = 0; i < mLength; i++) {
if (mSpellCheckSpans[i] == spellCheckSpan) {
+ // Resets id and progress to invalidate spell check span
mSpellCheckSpans[i].setSpellCheckInProgress(false);
mIds[i] = -1;
return;
@@ -211,6 +220,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
public void spellCheck(int start, int end) {
+ if (DBG) {
+ Log.d(TAG, "Start spell-checking: " + start + ", " + end);
+ }
final Locale locale = mTextView.getTextServicesLocale();
final boolean isSessionActive = isSessionActive();
if (mCurrentLocale == null || (!(mCurrentLocale.equals(locale)))) {
@@ -238,6 +250,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
}
+ if (DBG) {
+ Log.d(TAG, "new spell parser.");
+ }
// No available parser found in pool, create a new one
SpellParser[] newSpellParsers = new SpellParser[length + 1];
System.arraycopy(mSpellParsers, 0, newSpellParsers, 0, length);
@@ -260,13 +275,22 @@ public class SpellChecker implements SpellCheckerSessionListener {
for (int i = 0; i < mLength; i++) {
final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
- if (spellCheckSpan.isSpellCheckInProgress()) continue;
+ if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress()) continue;
final int start = editable.getSpanStart(spellCheckSpan);
final int end = editable.getSpanEnd(spellCheckSpan);
// Do not check this word if the user is currently editing it
- if (start >= 0 && end > start && (selectionEnd < start || selectionStart > end)) {
+ final boolean isEditing;
+ if (mIsSentenceSpellCheckSupported) {
+ // Allow the overlap of the cursor and the first boundary of the spell check span
+ // no to skip the spell check of the following word because the
+ // following word will never be spell-checked even if the user finishes composing
+ isEditing = selectionEnd <= start || selectionStart > end;
+ } else {
+ isEditing = selectionEnd < start || selectionStart > end;
+ }
+ if (start >= 0 && end > start && isEditing) {
final String word = (editable instanceof SpannableStringBuilder) ?
((SpannableStringBuilder) editable).substring(start, end) :
editable.subSequence(start, end).toString();
@@ -372,6 +396,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
private void scheduleNewSpellCheck() {
+ if (DBG) {
+ Log.i(TAG, "schedule new spell check.");
+ }
if (mSpellRunnable == null) {
mSpellRunnable = new Runnable() {
@Override
@@ -423,6 +450,20 @@ public class SpellChecker implements SpellCheckerSessionListener {
SuggestionSpan suggestionSpan = new SuggestionSpan(mTextView.getContext(), suggestions,
SuggestionSpan.FLAG_EASY_CORRECT | SuggestionSpan.FLAG_MISSPELLED);
+ // TODO: Remove mIsSentenceSpellCheckSupported by extracting an interface
+ // to share the logic of word level spell checker and sentence level spell checker
+ if (mIsSentenceSpellCheckSupported) {
+ final long key = TextUtils.packRangeInLong(start, end);
+ final SuggestionSpan tempSuggestionSpan = mSuggestionSpanCache.get(key);
+ if (tempSuggestionSpan != null) {
+ if (DBG) {
+ Log.i(TAG, "Cached span on the same position is cleard. "
+ + editable.subSequence(start, end));
+ }
+ editable.removeSpan(tempSuggestionSpan);
+ }
+ mSuggestionSpanCache.put(key, suggestionSpan);
+ }
editable.setSpan(suggestionSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTextView.invalidateRegion(start, end, false /* No cursor involved */);
@@ -447,10 +488,17 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
private void setRangeSpan(Editable editable, int start, int end) {
+ if (DBG) {
+ Log.d(TAG, "set next range span: " + start + ", " + end);
+ }
editable.setSpan(mRange, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
private void removeRangeSpan(Editable editable) {
+ if (DBG) {
+ Log.d(TAG, "Remove range span." + editable.getSpanStart(editable)
+ + editable.getSpanEnd(editable));
+ }
editable.removeSpan(mRange);
}
@@ -484,6 +532,9 @@ public class SpellChecker implements SpellCheckerSessionListener {
wordEnd = mWordIterator.getEnd(wordStart);
}
if (wordEnd == BreakIterator.DONE) {
+ if (DBG) {
+ Log.i(TAG, "No more spell check.");
+ }
removeRangeSpan(editable);
return;
}
@@ -499,47 +550,72 @@ public class SpellChecker implements SpellCheckerSessionListener {
boolean scheduleOtherSpellCheck = false;
if (mIsSentenceSpellCheckSupported) {
- int regionEnd;
if (wordIteratorWindowEnd < end) {
+ if (DBG) {
+ Log.i(TAG, "schedule other spell check.");
+ }
// Several batches needed on that region. Cut after last previous word
- regionEnd = mWordIterator.preceding(wordIteratorWindowEnd);
scheduleOtherSpellCheck = true;
- } else {
- regionEnd = mWordIterator.preceding(end);
}
- boolean correct = regionEnd != BreakIterator.DONE;
+ int spellCheckEnd = mWordIterator.preceding(wordIteratorWindowEnd);
+ boolean correct = spellCheckEnd != BreakIterator.DONE;
if (correct) {
- regionEnd = mWordIterator.getEnd(regionEnd);
- correct = regionEnd != BreakIterator.DONE;
+ spellCheckEnd = mWordIterator.getEnd(spellCheckEnd);
+ correct = spellCheckEnd != BreakIterator.DONE;
}
if (!correct) {
- editable.removeSpan(mRange);
- return;
- }
- // Stop spell checking when there are no characters in the range.
- if (wordEnd < start) {
- return;
- }
- // TODO: Find the start position of the sentence.
- final int spellCheckStart = wordStart;
- if (regionEnd <= spellCheckStart) {
+ if (DBG) {
+ Log.i(TAG, "Incorrect range span.");
+ }
+ removeRangeSpan(editable);
return;
}
- final int selectionStart = Selection.getSelectionStart(editable);
- final int selectionEnd = Selection.getSelectionEnd(editable);
- if (DBG) {
- Log.d(TAG, "addSpellCheckSpan: "
- + editable.subSequence(spellCheckStart, regionEnd)
- + ", regionEnd = " + regionEnd + ", spellCheckStart = "
- + spellCheckStart + ", sel start = " + selectionStart + ", sel end ="
- + selectionEnd);
- }
- // Do not check this word if the user is currently editing it
- if (spellCheckStart >= 0 && regionEnd > spellCheckStart
- && (selectionEnd < spellCheckStart || selectionStart > regionEnd)) {
- addSpellCheckSpan(editable, spellCheckStart, regionEnd);
- }
- wordStart = regionEnd;
+ do {
+ // TODO: Find the start position of the sentence.
+ int spellCheckStart = wordStart;
+ boolean createSpellCheckSpan = true;
+ // Cancel or merge overlapped spell check spans
+ for (int i = 0; i < mLength; ++i) {
+ final SpellCheckSpan spellCheckSpan = mSpellCheckSpans[i];
+ if (mIds[i] < 0 || spellCheckSpan.isSpellCheckInProgress()) {
+ continue;
+ }
+ final int spanStart = editable.getSpanStart(spellCheckSpan);
+ final int spanEnd = editable.getSpanEnd(spellCheckSpan);
+ if (spanEnd < spellCheckStart || spellCheckEnd < spanStart) {
+ // No need to merge
+ continue;
+ }
+ if (spanStart <= spellCheckStart && spellCheckEnd <= spanEnd) {
+ // There is a completely overlapped spell check span
+ // skip this span
+ createSpellCheckSpan = false;
+ if (DBG) {
+ Log.i(TAG, "The range is overrapped. Skip spell check.");
+ }
+ break;
+ }
+ removeSpellCheckSpan(spellCheckSpan);
+ spellCheckStart = Math.min(spanStart, spellCheckStart);
+ spellCheckEnd = Math.max(spanEnd, spellCheckEnd);
+ }
+
+ if (DBG) {
+ Log.d(TAG, "addSpellCheckSpan: "
+ + ", End = " + spellCheckEnd + ", Start = " + spellCheckStart
+ + ", next = " + scheduleOtherSpellCheck + "\n"
+ + editable.subSequence(spellCheckStart, spellCheckEnd));
+ }
+
+ // Stop spell checking when there are no characters in the range.
+ if (spellCheckEnd < start) {
+ break;
+ }
+ if (createSpellCheckSpan) {
+ addSpellCheckSpan(editable, spellCheckStart, spellCheckEnd);
+ }
+ } while (false);
+ wordStart = spellCheckEnd;
} else {
while (wordStart <= end) {
if (wordEnd >= start && wordEnd > wordStart) {
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index ba814d3..8c81343 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1512,6 +1512,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the start padding of the view, plus space for the start
* Drawable if any.
+ * @hide
*/
public int getCompoundPaddingStart() {
resolveDrawables();
@@ -1527,6 +1528,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the end padding of the view, plus space for the end
* Drawable if any.
+ * @hide
*/
public int getCompoundPaddingEnd() {
resolveDrawables();
@@ -1624,6 +1626,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the total start padding of the view, including the start
* Drawable if any.
+ * @hide
*/
public int getTotalPaddingStart() {
return getCompoundPaddingStart();
@@ -1632,6 +1635,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
/**
* Returns the total end padding of the view, including the end
* Drawable if any.
+ * @hide
*/
public int getTotalPaddingEnd() {
return getCompoundPaddingEnd();
@@ -1834,6 +1838,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
+ * @hide
*/
public void setCompoundDrawablesRelative(Drawable start, Drawable top,
Drawable end, Drawable bottom) {
@@ -1955,6 +1960,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
+ * @hide
*/
@android.view.RemotableViewMethod
public void setCompoundDrawablesRelativeWithIntrinsicBounds(int start, int top, int end,
@@ -1978,6 +1984,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
+ * @hide
*/
public void setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable start, Drawable top,
Drawable end, Drawable bottom) {
@@ -2024,6 +2031,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @attr ref android.R.styleable#TextView_drawableTop
* @attr ref android.R.styleable#TextView_drawableEnd
* @attr ref android.R.styleable#TextView_drawableBottom
+ * @hide
*/
public Drawable[] getCompoundDrawablesRelative() {
final Drawables dr = mDrawables;
@@ -4543,6 +4551,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ /**
+ * @hide
+ */
@Override
public int getResolvedLayoutDirection(Drawable who) {
if (who == null) return View.LAYOUT_DIRECTION_LTR;
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index 805c0a9..2cbd9cc 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -39,8 +39,8 @@ import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.os.Handler;
+import android.util.Log;
import android.util.TypedValue;
import android.view.ActionMode;
import android.view.ContextThemeWrapper;
@@ -110,10 +110,14 @@ public class ActionBarImpl extends ActionBar {
private int mCurWindowVisibility = View.VISIBLE;
+ private boolean mHiddenByApp;
+ private boolean mHiddenBySystem;
+ private boolean mShowingForMode;
+
+ private boolean mNowShowing = true;
+
private Animator mCurrentShowAnim;
- private Animator mCurrentModeAnim;
private boolean mShowHideAnimationEnabled;
- boolean mWasHiddenBeforeMode;
final AnimatorListener mHideListener = new AnimatorListenerAdapter() {
@Override
@@ -129,6 +133,9 @@ public class ActionBarImpl extends ActionBar {
mContainerView.setTransitioning(false);
mCurrentShowAnim = null;
completeDeferredDestroyActionMode();
+ if (mOverlayLayout != null) {
+ mOverlayLayout.requestFitSystemWindows();
+ }
}
};
@@ -430,16 +437,13 @@ public class ActionBarImpl extends ActionBar {
}
public ActionMode startActionMode(ActionMode.Callback callback) {
- boolean wasHidden = false;
if (mActionMode != null) {
- wasHidden = mWasHiddenBeforeMode;
mActionMode.finish();
}
mContextView.killMode();
ActionModeImpl mode = new ActionModeImpl(callback);
if (mode.dispatchOnCreate()) {
- mWasHiddenBeforeMode = !isShowing() || wasHidden;
mode.invalidate();
mContextView.initForMode(mode);
animateToMode(true);
@@ -584,21 +588,91 @@ public class ActionBarImpl extends ActionBar {
@Override
public void show() {
- show(true, false);
+ if (mHiddenByApp) {
+ mHiddenByApp = false;
+ updateVisibility(false);
+ }
}
- public void show(boolean markHiddenBeforeMode, boolean alwaysAnimate) {
+ private void showForActionMode() {
+ if (!mShowingForMode) {
+ mShowingForMode = true;
+ if (mOverlayLayout != null) {
+ mOverlayLayout.setShowingForActionMode(true);
+ }
+ updateVisibility(false);
+ }
+ }
+
+ public void showForSystem() {
+ if (mHiddenBySystem) {
+ mHiddenBySystem = false;
+ updateVisibility(true);
+ }
+ }
+
+ @Override
+ public void hide() {
+ if (!mHiddenByApp) {
+ mHiddenByApp = true;
+ updateVisibility(false);
+ }
+ }
+
+ private void hideForActionMode() {
+ if (mShowingForMode) {
+ mShowingForMode = false;
+ if (mOverlayLayout != null) {
+ mOverlayLayout.setShowingForActionMode(false);
+ }
+ updateVisibility(false);
+ }
+ }
+
+ public void hideForSystem() {
+ if (!mHiddenBySystem) {
+ mHiddenBySystem = true;
+ updateVisibility(true);
+ }
+ }
+
+ private static boolean checkShowingFlags(boolean hiddenByApp, boolean hiddenBySystem,
+ boolean showingForMode) {
+ if (showingForMode) {
+ return true;
+ } else if (hiddenByApp || hiddenBySystem) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private void updateVisibility(boolean fromSystem) {
+ // Based on the current state, should we be hidden or shown?
+ final boolean shown = checkShowingFlags(mHiddenByApp, mHiddenBySystem,
+ mShowingForMode);
+
+ if (shown) {
+ if (!mNowShowing) {
+ mNowShowing = true;
+ doShow(fromSystem);
+ }
+ } else {
+ if (mNowShowing) {
+ mNowShowing = false;
+ doHide(fromSystem);
+ }
+ }
+ }
+
+ public void doShow(boolean fromSystem) {
if (mCurrentShowAnim != null) {
mCurrentShowAnim.end();
}
- if (mTopVisibilityView.getVisibility() == View.VISIBLE) {
- if (markHiddenBeforeMode) mWasHiddenBeforeMode = false;
- return;
- }
mTopVisibilityView.setVisibility(View.VISIBLE);
if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
- || alwaysAnimate)) {
+ || fromSystem)) {
mTopVisibilityView.setAlpha(0);
mTopVisibilityView.setTranslationY(-mTopVisibilityView.getHeight());
AnimatorSet anim = new AnimatorSet();
@@ -617,6 +691,18 @@ public class ActionBarImpl extends ActionBar {
}
anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
com.android.internal.R.interpolator.decelerate_quad));
+ anim.setDuration(mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_mediumAnimTime));
+ // If this is being shown from the system, add a small delay.
+ // This is because we will also be animating in the status bar,
+ // and these two elements can't be done in lock-step. So we give
+ // a little time for the status bar to start its animation before
+ // the action bar animates. (This corresponds to the corresponding
+ // case when hiding, where the status bar has a small delay before
+ // starting.)
+ if (fromSystem) {
+ anim.setStartDelay(100);
+ }
anim.addListener(mShowListener);
mCurrentShowAnim = anim;
anim.start();
@@ -625,23 +711,18 @@ public class ActionBarImpl extends ActionBar {
mContainerView.setTranslationY(0);
mShowListener.onAnimationEnd(null);
}
+ if (mOverlayLayout != null) {
+ mOverlayLayout.requestFitSystemWindows();
+ }
}
- @Override
- public void hide() {
- hide(false);
- }
-
- public void hide(boolean alwaysAnimate) {
+ public void doHide(boolean fromSystem) {
if (mCurrentShowAnim != null) {
mCurrentShowAnim.end();
}
- if (mTopVisibilityView.getVisibility() == View.GONE) {
- return;
- }
if (mCurWindowVisibility == View.VISIBLE && (mShowHideAnimationEnabled
- || alwaysAnimate)) {
+ || fromSystem)) {
mTopVisibilityView.setAlpha(1);
mContainerView.setTransitioning(true);
AnimatorSet anim = new AnimatorSet();
@@ -660,6 +741,8 @@ public class ActionBarImpl extends ActionBar {
}
anim.setInterpolator(AnimationUtils.loadInterpolator(mContext,
com.android.internal.R.interpolator.accelerate_quad));
+ anim.setDuration(mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_mediumAnimTime));
anim.addListener(mHideListener);
mCurrentShowAnim = anim;
anim.start();
@@ -669,15 +752,18 @@ public class ActionBarImpl extends ActionBar {
}
public boolean isShowing() {
- return mTopVisibilityView.getVisibility() == View.VISIBLE;
+ return mNowShowing;
+ }
+
+ public boolean isSystemShowing() {
+ return !mHiddenBySystem;
}
void animateToMode(boolean toActionMode) {
if (toActionMode) {
- show(false, false);
- }
- if (mCurrentModeAnim != null) {
- mCurrentModeAnim.end();
+ showForActionMode();
+ } else {
+ hideForActionMode();
}
mActionView.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
@@ -736,11 +822,13 @@ public class ActionBarImpl extends ActionBar {
return;
}
- // If we were hidden before the mode was shown, defer the onDestroy
- // callback until the animation is finished and associated relayout
- // is about to happen. This lets apps better anticipate visibility
- // and layout behavior.
- if (mWasHiddenBeforeMode) {
+ // If this change in state is going to cause the action bar
+ // to be hidden, defer the onDestroy callback until the animation
+ // is finished and associated relayout is about to happen. This lets
+ // apps better anticipate visibility and layout behavior.
+ if (!checkShowingFlags(mHiddenByApp, mHiddenBySystem, false)) {
+ // With the current state but the action bar hidden, our
+ // overall showing state is going to be false.
mDeferredDestroyActionMode = this;
mDeferredModeDestroyCallback = mCallback;
} else {
@@ -754,10 +842,6 @@ public class ActionBarImpl extends ActionBar {
mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
mActionMode = null;
-
- if (mWasHiddenBeforeMode) {
- hide();
- }
}
@Override
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 51bbdf1..4f2afa7 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -19,15 +19,17 @@ package com.android.internal.app;
import com.android.internal.R;
import com.android.internal.content.PackageMonitor;
+import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.LabeledIntent;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
@@ -38,8 +40,8 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
-import android.widget.CheckBox;
-import android.widget.CompoundButton;
+import android.widget.Button;
+import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
@@ -56,12 +58,19 @@ import java.util.Set;
* which there is more than one matching activity, allowing the user to decide
* which to go to. It is not normally used directly by application developers.
*/
-public class ResolverActivity extends AlertActivity implements
- DialogInterface.OnClickListener, CheckBox.OnCheckedChangeListener {
+public class ResolverActivity extends AlertActivity implements AdapterView.OnItemClickListener {
+ private static final String TAG = "ResolverActivity";
+
private ResolveListAdapter mAdapter;
- private CheckBox mAlwaysCheck;
- private TextView mClearDefaultHint;
private PackageManager mPm;
+ private boolean mAlwaysUseOption;
+ private boolean mShowExtended;
+ private GridView mGrid;
+ private Button mAlwaysButton;
+ private Button mOnceButton;
+ private int mIconDpi;
+ private int mIconSize;
+ private int mMaxColumns;
private boolean mRegistered;
private final PackageMonitor mPackageMonitor = new PackageMonitor() {
@@ -91,33 +100,38 @@ public class ResolverActivity extends AlertActivity implements
protected void onCreate(Bundle savedInstanceState, Intent intent,
CharSequence title, Intent[] initialIntents, List<ResolveInfo> rList,
boolean alwaysUseOption) {
+ setTheme(R.style.Theme_DeviceDefault_Light_Dialog_Alert);
super.onCreate(savedInstanceState);
mPm = getPackageManager();
+ mAlwaysUseOption = alwaysUseOption;
+ mMaxColumns = getResources().getInteger(R.integer.config_maxResolverActivityColumns);
intent.setComponent(null);
AlertController.AlertParams ap = mAlertParams;
ap.mTitle = title;
- ap.mOnClickListener = this;
mPackageMonitor.register(this, getMainLooper(), false);
mRegistered = true;
- if (alwaysUseOption) {
- LayoutInflater inflater = (LayoutInflater) getSystemService(
- Context.LAYOUT_INFLATER_SERVICE);
- ap.mView = inflater.inflate(R.layout.always_use_checkbox, null);
- mAlwaysCheck = (CheckBox)ap.mView.findViewById(com.android.internal.R.id.alwaysUse);
- mAlwaysCheck.setText(R.string.alwaysUse);
- mAlwaysCheck.setOnCheckedChangeListener(this);
- mClearDefaultHint = (TextView)ap.mView.findViewById(
- com.android.internal.R.id.clearDefaultHint);
- mClearDefaultHint.setVisibility(View.GONE);
- }
+ final ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
+ mIconDpi = am.getLauncherLargeIconDensity();
+ mIconSize = am.getLauncherLargeIconSize();
+
mAdapter = new ResolveListAdapter(this, intent, initialIntents, rList);
int count = mAdapter.getCount();
if (count > 1) {
- ap.mAdapter = mAdapter;
+ ap.mView = getLayoutInflater().inflate(R.layout.resolver_grid, null);
+ mGrid = (GridView) ap.mView.findViewById(R.id.resolver_grid);
+ mGrid.setAdapter(mAdapter);
+ mGrid.setOnItemClickListener(this);
+ mGrid.setOnItemLongClickListener(new ItemLongClickListener());
+
+ if (alwaysUseOption) {
+ mGrid.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+ }
+
+ resizeGrid();
} else if (count == 1) {
startActivity(mAdapter.intentForPosition(0));
mPackageMonitor.unregister();
@@ -125,17 +139,57 @@ public class ResolverActivity extends AlertActivity implements
finish();
return;
} else {
- ap.mMessage = getResources().getText(com.android.internal.R.string.noApplications);
+ ap.mMessage = getResources().getText(R.string.noApplications);
}
setupAlert();
- ListView lv = mAlert.getListView();
- if (lv != null) {
- lv.setOnItemLongClickListener(new ItemLongClickListener());
+ if (alwaysUseOption) {
+ final ViewGroup buttonLayout = (ViewGroup) findViewById(R.id.button_bar);
+ buttonLayout.setVisibility(View.VISIBLE);
+ mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
+ mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
}
}
+ void resizeGrid() {
+ final int itemCount = mAdapter.getCount();
+ mGrid.setNumColumns(Math.min(itemCount, mMaxColumns));
+ }
+
+ Drawable getIcon(Resources res, int resId) {
+ Drawable result;
+ try {
+ result = res.getDrawableForDensity(resId, mIconDpi);
+ } catch (Resources.NotFoundException e) {
+ result = null;
+ }
+
+ return result;
+ }
+
+ Drawable loadIconForResolveInfo(ResolveInfo ri) {
+ Drawable dr;
+ try {
+ if (ri.resolvePackageName != null && ri.icon != 0) {
+ dr = getIcon(mPm.getResourcesForApplication(ri.resolvePackageName), ri.icon);
+ if (dr != null) {
+ return dr;
+ }
+ }
+ final int iconRes = ri.getIconResource();
+ if (iconRes != 0) {
+ dr = getIcon(mPm.getResourcesForApplication(ri.activityInfo.packageName), iconRes);
+ if (dr != null) {
+ return dr;
+ }
+ }
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Couldn't find resources for package", e);
+ }
+ return ri.loadIcon(mPm);
+ }
+
@Override
protected void onRestart() {
super.onRestart();
@@ -155,11 +209,28 @@ public class ResolverActivity extends AlertActivity implements
}
}
- public void onClick(DialogInterface dialog, int which) {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (mAlwaysUseOption) {
+ final int checkedPos = mGrid.getCheckedItemPosition();
+ final boolean enabled = checkedPos != GridView.INVALID_POSITION;
+ mAlwaysButton.setEnabled(enabled);
+ mOnceButton.setEnabled(enabled);
+ } else {
+ startSelected(position, false);
+ }
+ }
+
+ public void onButtonClick(View v) {
+ final int id = v.getId();
+ startSelected(mGrid.getCheckedItemPosition(), id == R.id.button_always);
+ dismiss();
+ }
+
+ void startSelected(int which, boolean always) {
ResolveInfo ri = mAdapter.resolveInfoForPosition(which);
Intent intent = mAdapter.intentForPosition(which);
- boolean alwaysCheck = (mAlwaysCheck != null && mAlwaysCheck.isChecked());
- onIntentSelected(ri, intent, alwaysCheck);
+ onIntentSelected(ri, intent, always);
finish();
}
@@ -249,6 +320,12 @@ public class ResolverActivity extends AlertActivity implements
}
}
+ void showAppDetails(ResolveInfo ri) {
+ Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
+ .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
+ startActivity(in);
+ }
+
private final class DisplayResolveInfo {
ResolveInfo ri;
CharSequence displayLabel;
@@ -285,12 +362,18 @@ public class ResolverActivity extends AlertActivity implements
}
public void handlePackagesChanged() {
+ final int oldItemCount = getCount();
rebuildList();
notifyDataSetChanged();
if (mList.size() <= 0) {
// We no longer have any items... just finish the activity.
finish();
}
+
+ final int newItemCount = getCount();
+ if (newItemCount != oldItemCount) {
+ resizeGrid();
+ }
}
private void rebuildList() {
@@ -299,7 +382,7 @@ public class ResolverActivity extends AlertActivity implements
} else {
mCurrentResolveList = mPm.queryIntentActivities(
mIntent, PackageManager.MATCH_DEFAULT_ONLY
- | (mAlwaysCheck != null ? PackageManager.GET_RESOLVED_FILTER : 0));
+ | (mAlwaysUseOption ? PackageManager.GET_RESOLVED_FILTER : 0));
}
int N;
if ((mCurrentResolveList != null) && ((N = mCurrentResolveList.size()) > 0)) {
@@ -363,6 +446,7 @@ public class ResolverActivity extends AlertActivity implements
r0 = mCurrentResolveList.get(0);
int start = 0;
CharSequence r0Label = r0.loadLabel(mPm);
+ mShowExtended = false;
for (int i = 1; i < N; i++) {
if (r0Label == null) {
r0Label = r0.activityInfo.packageName;
@@ -393,6 +477,7 @@ public class ResolverActivity extends AlertActivity implements
// No duplicate labels. Use label for entry at start
mList.add(new DisplayResolveInfo(ro, roLabel, null, null));
} else {
+ mShowExtended = true;
boolean usePkg = false;
CharSequence startApp = ro.activityInfo.applicationInfo.loadLabel(mPm);
if (startApp == null) {
@@ -473,6 +558,11 @@ public class ResolverActivity extends AlertActivity implements
if (convertView == null) {
view = mInflater.inflate(
com.android.internal.R.layout.resolve_list_item, parent, false);
+
+ // Fix the icon size even if we have different sized resources
+ ImageView icon = (ImageView)view.findViewById(R.id.icon);
+ ViewGroup.LayoutParams lp = (ViewGroup.LayoutParams) icon.getLayoutParams();
+ lp.width = lp.height = mIconSize;
} else {
view = convertView;
}
@@ -485,37 +575,25 @@ public class ResolverActivity extends AlertActivity implements
TextView text2 = (TextView)view.findViewById(com.android.internal.R.id.text2);
ImageView icon = (ImageView)view.findViewById(R.id.icon);
text.setText(info.displayLabel);
- if (info.extendedInfo != null) {
+ if (mShowExtended) {
text2.setVisibility(View.VISIBLE);
text2.setText(info.extendedInfo);
} else {
text2.setVisibility(View.GONE);
}
if (info.displayIcon == null) {
- info.displayIcon = info.ri.loadIcon(mPm);
+ info.displayIcon = loadIconForResolveInfo(info.ri);
}
icon.setImageDrawable(info.displayIcon);
}
}
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (mClearDefaultHint == null) return;
-
- if(isChecked) {
- mClearDefaultHint.setVisibility(View.VISIBLE);
- } else {
- mClearDefaultHint.setVisibility(View.GONE);
- }
- }
-
class ItemLongClickListener implements AdapterView.OnItemLongClickListener {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
ResolveInfo ri = mAdapter.resolveInfoForPosition(position);
- Intent in = new Intent().setAction("android.settings.APPLICATION_DETAILS_SETTINGS")
- .setData(Uri.fromParts("package", ri.activityInfo.packageName, null));
- startActivity(in);
+ showAppDetails(ri);
return true;
}
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
index d59585f..8b222f0 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -24,20 +24,12 @@ import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
import android.net.NetworkStats;
import android.os.StrictMode;
import android.os.SystemClock;
-import android.util.Slog;
import com.android.internal.util.ProcFileReader;
-import com.google.android.collect.Lists;
-import com.google.android.collect.Sets;
-import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
-import java.io.FileReader;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.StringTokenizer;
import libcore.io.IoUtils;
@@ -50,14 +42,10 @@ public class NetworkStatsFactory {
// TODO: consider moving parsing to native code
- /** Path to {@code /proc/net/dev}. */
- @Deprecated
- private final File mStatsIface;
- /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
- @Deprecated
- private final File mStatsXtIface;
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
private final File mStatsXtIfaceAll;
+ /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
+ private final File mStatsXtIfaceFmt;
/** Path to {@code /proc/net/xt_qtaguid/stats}. */
private final File mStatsXtUid;
@@ -67,28 +55,20 @@ public class NetworkStatsFactory {
// @VisibleForTesting
public NetworkStatsFactory(File procRoot) {
- mStatsIface = new File(procRoot, "net/dev");
- mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
- mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat");
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
+ mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
+ mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
}
/**
- * Parse and return interface-level summary {@link NetworkStats}. Values
- * monotonically increase since device boot, and may include details about
- * inactive interfaces.
+ * Parse and return interface-level summary {@link NetworkStats} measured
+ * using {@code /proc/net/dev} style hooks, which may include non IP layer
+ * traffic. Values monotonically increase since device boot, and may include
+ * details about inactive interfaces.
*
* @throws IllegalStateException when problem parsing stats.
*/
- public NetworkStats readNetworkStatsSummary() throws IllegalStateException {
- if (mStatsXtIfaceAll.exists()) {
- return readNetworkStatsSummarySingleFile();
- } else {
- return readNetworkStatsSummaryMultipleFiles();
- }
- }
-
- private NetworkStats readNetworkStatsSummarySingleFile() {
+ public NetworkStats readNetworkStatsSummaryDev() throws IllegalStateException {
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
@@ -137,79 +117,40 @@ public class NetworkStatsFactory {
}
/**
- * @deprecated remove once {@code iface_stat_all} is merged to all kernels.
+ * Parse and return interface-level summary {@link NetworkStats}. Designed
+ * to return only IP layer traffic. Values monotonically increase since
+ * device boot, and may include details about inactive interfaces.
+ *
+ * @throws IllegalStateException when problem parsing stats.
*/
- @Deprecated
- private NetworkStats readNetworkStatsSummaryMultipleFiles() {
+ public NetworkStats readNetworkStatsSummaryXt() throws IllegalStateException {
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
+ // return null when kernel doesn't support
+ if (!mStatsXtIfaceFmt.exists()) return null;
+
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
final NetworkStats.Entry entry = new NetworkStats.Entry();
- final HashSet<String> knownIfaces = Sets.newHashSet();
- final HashSet<String> activeIfaces = Sets.newHashSet();
-
- // collect any historical stats and active state
- for (String iface : fileListWithoutNull(mStatsXtIface)) {
- final File ifacePath = new File(mStatsXtIface, iface);
-
- final long active = readSingleLongFromFile(new File(ifacePath, "active"));
- if (active == 1) {
- knownIfaces.add(iface);
- activeIfaces.add(iface);
- } else if (active == 0) {
- knownIfaces.add(iface);
- } else {
- continue;
- }
-
- entry.iface = iface;
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
- entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
- entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
- entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
+ ProcFileReader reader = null;
+ try {
+ // open and consume header line
+ reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceFmt));
+ reader.finishLine();
- stats.addValues(entry);
- }
+ while (reader.hasMoreData()) {
+ entry.iface = reader.nextString();
+ entry.uid = UID_ALL;
+ entry.set = SET_ALL;
+ entry.tag = TAG_NONE;
- final ArrayList<String> values = Lists.newArrayList();
+ entry.rxBytes = reader.nextLong();
+ entry.rxPackets = reader.nextLong();
+ entry.txBytes = reader.nextLong();
+ entry.txPackets = reader.nextLong();
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new FileReader(mStatsIface));
-
- // skip first two header lines
- reader.readLine();
- reader.readLine();
-
- // parse remaining lines
- String line;
- while ((line = reader.readLine()) != null) {
- splitLine(line, values);
-
- try {
- entry.iface = values.get(0);
- entry.uid = UID_ALL;
- entry.set = SET_ALL;
- entry.tag = TAG_NONE;
- entry.rxBytes = Long.parseLong(values.get(1));
- entry.rxPackets = Long.parseLong(values.get(2));
- entry.txBytes = Long.parseLong(values.get(9));
- entry.txPackets = Long.parseLong(values.get(10));
-
- if (activeIfaces.contains(entry.iface)) {
- // combine stats when iface is active
- stats.combineValues(entry);
- } else if (!knownIfaces.contains(entry.iface)) {
- // add stats when iface is unknown
- stats.addValues(entry);
- }
- } catch (NumberFormatException e) {
- Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
- }
+ stats.addValues(entry);
+ reader.finishLine();
}
} catch (NullPointerException e) {
throw new IllegalStateException("problem parsing stats: " + e);
@@ -221,7 +162,6 @@ public class NetworkStatsFactory {
IoUtils.closeQuietly(reader);
StrictMode.setThreadPolicy(savedPolicy);
}
-
return stats;
}
@@ -286,41 +226,4 @@ public class NetworkStatsFactory {
return stats;
}
-
- /**
- * Split given line into {@link ArrayList}.
- */
- @Deprecated
- private static void splitLine(String line, ArrayList<String> outSplit) {
- outSplit.clear();
-
- final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:");
- while (t.hasMoreTokens()) {
- outSplit.add(t.nextToken());
- }
- }
-
- /**
- * Utility method to read a single plain-text {@link Long} from the given
- * {@link File}, usually from a {@code /proc/} filesystem.
- */
- private static long readSingleLongFromFile(File file) {
- try {
- final byte[] buffer = IoUtils.readFileAsByteArray(file.toString());
- return Long.parseLong(new String(buffer).trim());
- } catch (NumberFormatException e) {
- return -1;
- } catch (IOException e) {
- return -1;
- }
- }
-
- /**
- * Wrapper for {@link File#list()} that returns empty array instead of
- * {@code null}.
- */
- private static String[] fileListWithoutNull(File file) {
- final String[] list = file.list();
- return list != null ? list : new String[0];
- }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 86118b1..5157385 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -5719,7 +5719,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (SystemProperties.getBoolean(PROP_QTAGUID_ENABLED, false)) {
try {
- mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummary();
+ mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummaryDev();
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuItemView.java b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
index d5c2018..449194b 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuItemView.java
@@ -70,8 +70,13 @@ public class ActionMenuItemView extends TextView
setOnClickListener(this);
setOnLongClickListener(this);
- // Save the inflated padding for later, we'll need it.
- mSavedPaddingLeft = getPaddingLeft();
+ mSavedPaddingLeft = -1;
+ }
+
+ @Override
+ public void setPadding(int l, int t, int r, int b) {
+ mSavedPaddingLeft = l;
+ super.setPadding(l, t, r, b);
}
public MenuItemImpl getItemData() {
@@ -217,8 +222,9 @@ public class ActionMenuItemView extends TextView
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final boolean textVisible = hasText();
- if (textVisible) {
- setPadding(mSavedPaddingLeft, getPaddingTop(), getPaddingRight(), getPaddingBottom());
+ if (textVisible && mSavedPaddingLeft >= 0) {
+ super.setPadding(mSavedPaddingLeft, getPaddingTop(),
+ getPaddingRight(), getPaddingBottom());
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -240,7 +246,7 @@ public class ActionMenuItemView extends TextView
// a little coercion. Pad in to center the icon after we've measured.
final int w = getMeasuredWidth();
final int dw = mIcon.getIntrinsicWidth();
- setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom());
+ super.setPadding((w - dw) / 2, getPaddingTop(), getPaddingRight(), getPaddingBottom());
}
}
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuView.java b/core/java/com/android/internal/view/menu/ActionMenuView.java
index af67d55..f54575b 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuView.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuView.java
@@ -17,6 +17,7 @@ package com.android.internal.view.menu;
import android.content.Context;
import android.content.res.Configuration;
+import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
@@ -25,6 +26,8 @@ import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.LinearLayout;
+import com.android.internal.R;
+
/**
* @hide
*/
@@ -43,6 +46,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
private int mMinCellSize;
private int mGeneratedItemPadding;
private int mMeasuredExtraWidth;
+ private int mMaxItemHeight;
public ActionMenuView(Context context) {
this(context, null);
@@ -54,6 +58,11 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
final float density = context.getResources().getDisplayMetrics().density;
mMinCellSize = (int) (MIN_CELL_SIZE * density);
mGeneratedItemPadding = (int) (GENERATED_ITEM_PADDING * density);
+
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ActionBar,
+ R.attr.actionBarStyle, 0);
+ mMaxItemHeight = a.getDimensionPixelSize(R.styleable.ActionBar_height, 0);
+ a.recycle();
}
public void setPresenter(ActionMenuPresenter presenter) {
@@ -116,6 +125,11 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
final int widthPadding = getPaddingLeft() + getPaddingRight();
final int heightPadding = getPaddingTop() + getPaddingBottom();
+ final int itemHeightSpec = heightMode == MeasureSpec.EXACTLY
+ ? MeasureSpec.makeMeasureSpec(heightSize - heightPadding, MeasureSpec.EXACTLY)
+ : MeasureSpec.makeMeasureSpec(
+ Math.min(mMaxItemHeight, heightSize - heightPadding), MeasureSpec.AT_MOST);
+
widthSize -= widthPadding;
// Divide the view into cells.
@@ -167,7 +181,7 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
final int cellsAvailable = lp.isOverflowButton ? 1 : cellsRemaining;
final int cellsUsed = measureChildForCells(child, cellSize, cellsAvailable,
- heightMeasureSpec, heightPadding);
+ itemHeightSpec, heightPadding);
maxCellsUsed = Math.max(maxCellsUsed, cellsUsed);
if (lp.expandable) expandableItemCount++;
@@ -298,7 +312,6 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
// Remeasure any items that have had extra space allocated to them.
if (needsExpansion) {
- int heightSpec = MeasureSpec.makeMeasureSpec(heightSize - heightPadding, heightMode);
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
@@ -306,7 +319,8 @@ public class ActionMenuView extends LinearLayout implements MenuBuilder.ItemInvo
if (!lp.expanded) continue;
final int width = lp.cellsUsed * cellSize + lp.extraPixels;
- child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightSpec);
+ child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ itemHeightSpec);
}
}
diff --git a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
index d1652df..a129496 100644
--- a/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
+++ b/core/java/com/android/internal/widget/ActionBarOverlayLayout.java
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.View;
import android.widget.FrameLayout;
@@ -76,6 +77,26 @@ public class ActionBarOverlayLayout extends FrameLayout {
}
}
+ public void setShowingForActionMode(boolean showing) {
+ if (showing) {
+ // Here's a fun hack: if the status bar is currently being hidden,
+ // and the application has asked for stable content insets, then
+ // we will end up with the action mode action bar being shown
+ // without the status bar, but moved below where the status bar
+ // would be. Not nice. Trying to have this be positioned
+ // correctly is not easy (basically we need yet *another* content
+ // inset from the window manager to know where to put it), so
+ // instead we will just temporarily force the status bar to be shown.
+ if ((getWindowSystemUiVisibility() & (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | SYSTEM_UI_FLAG_LAYOUT_STABLE))
+ == (SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE)) {
+ setDisabledSystemUiVisibility(SYSTEM_UI_FLAG_FULLSCREEN);
+ }
+ } else {
+ setDisabledSystemUiVisibility(0);
+ }
+ }
+
@Override
public void onWindowSystemUiVisibilityChanged(int visible) {
super.onWindowSystemUiVisibilityChanged(visible);
@@ -83,11 +104,13 @@ public class ActionBarOverlayLayout extends FrameLayout {
final int diff = mLastSystemUiVisibility ^ visible;
mLastSystemUiVisibility = visible;
final boolean barVisible = (visible&SYSTEM_UI_FLAG_FULLSCREEN) == 0;
- final boolean wasVisible = mActionBar != null ? mActionBar.isShowing() : true;
- if (barVisible != wasVisible || (diff&SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
+ final boolean wasVisible = mActionBar != null ? mActionBar.isSystemShowing() : true;
+ if (mActionBar != null) {
+ if (barVisible) mActionBar.showForSystem();
+ else mActionBar.hideForSystem();
+ }
+ if ((diff&SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
if (mActionBar != null) {
- if (barVisible) mActionBar.show(true, true);
- else mActionBar.hide(true);
requestFitSystemWindows();
}
}