summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/ApplicationPackageManager.java28
-rw-r--r--core/java/android/app/SearchDialog.java23
-rw-r--r--core/java/android/content/pm/ActivityInfo.java7
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl17
-rw-r--r--core/java/android/content/pm/PackageParser.java9
-rwxr-xr-xcore/java/android/content/pm/ParceledListSlice.aidl19
-rw-r--r--core/java/android/content/pm/ParceledListSlice.java170
-rw-r--r--core/java/android/content/res/AssetManager.java4
-rw-r--r--core/java/android/content/res/Configuration.java124
-rwxr-xr-xcore/java/android/content/res/Resources.java1
-rw-r--r--core/java/android/hardware/Camera.java133
-rw-r--r--core/java/android/hardware/Sensor.java7
-rw-r--r--core/java/android/hardware/SensorEvent.java58
-rw-r--r--core/java/android/hardware/usb/UsbDeviceConnection.java12
-rw-r--r--core/java/android/net/INetworkPolicyManager.aidl34
-rw-r--r--core/java/android/net/LinkProperties.java3
-rw-r--r--core/java/android/net/MobileDataStateTracker.java15
-rw-r--r--core/java/android/net/NetworkPolicyManager.java68
-rw-r--r--core/java/android/net/NetworkUtils.java110
-rw-r--r--core/java/android/net/RouteInfo.java59
-rw-r--r--core/java/android/os/INetworkManagementService.aidl17
-rw-r--r--core/java/android/os/storage/StorageVolume.java39
-rw-r--r--core/java/android/server/BluetoothInputProfileHandler.java26
-rw-r--r--core/java/android/server/BluetoothPanProfileHandler.java28
-rwxr-xr-x[-rw-r--r--]core/java/android/server/BluetoothService.java131
-rw-r--r--core/java/android/view/LayoutInflater.java82
-rw-r--r--core/java/android/view/View.java48
-rw-r--r--core/java/android/view/ViewDebug.java192
-rw-r--r--core/java/android/view/WindowManagerPolicy.java30
-rw-r--r--core/java/android/view/accessibility/AccessibilityRecord.java2
-rw-r--r--core/java/android/widget/ExpandableListView.java27
-rw-r--r--core/java/android/widget/LinearLayout.java89
32 files changed, 1123 insertions, 489 deletions
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 85918cf..4cff12f 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -34,6 +34,7 @@ import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
+import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.ProviderInfo;
@@ -44,6 +45,7 @@ import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.os.Parcel;
import android.os.Process;
import android.os.RemoteException;
import android.util.Log;
@@ -378,19 +380,41 @@ final class ApplicationPackageManager extends PackageManager {
throw new NameNotFoundException("No shared userid for user:"+sharedUserName);
}
+ @SuppressWarnings("unchecked")
@Override
public List<PackageInfo> getInstalledPackages(int flags) {
try {
- return mPM.getInstalledPackages(flags);
+ final List<PackageInfo> packageInfos = new ArrayList<PackageInfo>();
+ PackageInfo lastItem = null;
+ ParceledListSlice<PackageInfo> slice;
+
+ do {
+ final String lastKey = lastItem != null ? lastItem.packageName : null;
+ slice = mPM.getInstalledPackages(flags, lastKey);
+ lastItem = slice.populateList(packageInfos, PackageInfo.CREATOR);
+ } while (!slice.isLastSlice());
+
+ return packageInfos;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
}
+ @SuppressWarnings("unchecked")
@Override
public List<ApplicationInfo> getInstalledApplications(int flags) {
try {
- return mPM.getInstalledApplications(flags);
+ final List<ApplicationInfo> applicationInfos = new ArrayList<ApplicationInfo>();
+ ApplicationInfo lastItem = null;
+ ParceledListSlice<ApplicationInfo> slice;
+
+ do {
+ final String lastKey = lastItem != null ? lastItem.packageName : null;
+ slice = mPM.getInstalledApplications(flags, lastKey);
+ lastItem = slice.populateList(applicationInfos, ApplicationInfo.CREATOR);
+ } while (!slice.isLastSlice());
+
+ return applicationInfos;
} catch (RemoteException e) {
throw new RuntimeException("Package manager has died", e);
}
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index db8d5e9..9cb57be 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -29,12 +29,13 @@ import android.content.res.Configuration;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
-import android.os.SystemClock;
import android.speech.RecognizerIntent;
import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
+import android.util.TypedValue;
+import android.view.ActionMode;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -50,9 +51,6 @@ import android.widget.LinearLayout;
import android.widget.SearchView;
import android.widget.TextView;
-import java.util.WeakHashMap;
-import java.util.concurrent.atomic.AtomicLong;
-
/**
* Search dialog. This is controlled by the
* SearchManager and runs in the current foreground process.
@@ -110,13 +108,20 @@ public class SearchDialog extends Dialog {
}
};
+ static int resolveDialogTheme(Context context) {
+ TypedValue outValue = new TypedValue();
+ context.getTheme().resolveAttribute(com.android.internal.R.attr.searchDialogTheme,
+ outValue, true);
+ return outValue.resourceId;
+ }
+
/**
* Constructor - fires it up and makes it look like the search UI.
*
* @param context Application Context we can use for system acess
*/
public SearchDialog(Context context, SearchManager searchManager) {
- super(context, com.android.internal.R.style.Theme_SearchBar);
+ super(context, resolveDialogTheme(context));
// Save voice intent for later queries/launching
mVoiceWebSearchIntent = new Intent(RecognizerIntent.ACTION_WEB_SEARCH);
@@ -642,6 +647,14 @@ public class SearchDialog extends Dialog {
}
return super.dispatchKeyEventPreIme(event);
}
+
+ /**
+ * Don't allow action modes in a SearchBar, it looks silly.
+ */
+ @Override
+ public ActionMode startActionModeForChild(View child, ActionMode.Callback callback) {
+ return null;
+ }
}
private boolean isEmpty(AutoCompleteTextView actv) {
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 64c437d..4285388 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -340,6 +340,12 @@ public class ActivityInfo extends ComponentInfo
public static final int CONFIG_SCREEN_SIZE = 0x0400;
/**
* Bit in {@link #configChanges} that indicates that the activity
+ * can itself handle the smallest screen size. Set from the
+ * {@link android.R.attr#configChanges} attribute.
+ */
+ public static final int CONFIG_SMALLEST_SCREEN_SIZE = 0x0800;
+ /**
+ * Bit in {@link #configChanges} that indicates that the activity
* can itself handle changes to the font scaling factor. Set from the
* {@link android.R.attr#configChanges} attribute. This is
* not a core resource configutation, but a higher-level value, so its
@@ -364,6 +370,7 @@ public class ActivityInfo extends ComponentInfo
0x0800, // SCREEN LAYOUT
0x1000, // UI MODE
0x0200, // SCREEN SIZE
+ 0x2000, // SMALLEST SCREEN SIZE
};
/** @hide
* Convert Java change bits to native.
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 11cd446..37b6822 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -30,6 +30,7 @@ import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
import android.content.pm.PackageInfo;
+import android.content.pm.ParceledListSlice;
import android.content.pm.ProviderInfo;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -110,9 +111,21 @@ interface IPackageManager {
List<ResolveInfo> queryIntentServices(in Intent intent,
String resolvedType, int flags);
- List<PackageInfo> getInstalledPackages(int flags);
+ /**
+ * This implements getInstalledPackages via a "last returned row"
+ * mechanism that is not exposed in the API. This is to get around the IPC
+ * limit that kicks in when flags are included that bloat up the data
+ * returned.
+ */
+ ParceledListSlice getInstalledPackages(int flags, in String lastRead);
- List<ApplicationInfo> getInstalledApplications(int flags);
+ /**
+ * This implements getInstalledApplications via a "last returned row"
+ * mechanism that is not exposed in the API. This is to get around the IPC
+ * limit that kicks in when flags are included that bloat up the data
+ * returned.
+ */
+ ParceledListSlice getInstalledApplications(int flags, in String lastRead);
/**
* Retrieve all applications that are marked as persistent.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b8cb165..9ff324b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -396,7 +396,7 @@ public class PackageParser {
int cookie = assmgr.addAssetPath(mArchiveSourcePath);
if (cookie != 0) {
res = new Resources(assmgr, metrics, null);
- assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
assetError = false;
@@ -596,7 +596,7 @@ public class PackageParser {
AssetManager assmgr = null;
try {
assmgr = new AssetManager();
- assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Build.VERSION.RESOURCES_SDK_INT);
int cookie = assmgr.addAssetPath(packageFilePath);
parser = assmgr.openXmlResourceParser(cookie, "AndroidManifest.xml");
@@ -1942,8 +1942,9 @@ public class PackageParser {
com.android.internal.R.styleable.AndroidManifestActivity_configChanges,
0);
if (owner.applicationInfo.targetSdkVersion
- < android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- a.info.configChanges |= ActivityInfo.CONFIG_SCREEN_SIZE;
+ < android.os.Build.VERSION_CODES.HONEYCOMB_MR2) {
+ a.info.configChanges |= ActivityInfo.CONFIG_SCREEN_SIZE
+ | ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
}
a.info.softInputMode = sa.getInt(
com.android.internal.R.styleable.AndroidManifestActivity_windowSoftInputMode,
diff --git a/core/java/android/content/pm/ParceledListSlice.aidl b/core/java/android/content/pm/ParceledListSlice.aidl
new file mode 100755
index 0000000..c02cc6a
--- /dev/null
+++ b/core/java/android/content/pm/ParceledListSlice.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+parcelable ParceledListSlice;
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
new file mode 100644
index 0000000..f3a98db
--- /dev/null
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.List;
+
+/**
+ * Builds up a parcel that is discarded when written to another parcel or
+ * written to a list. This is useful for API that sends huge lists across a
+ * Binder that may be larger than the IPC limit.
+ *
+ * @hide
+ */
+public class ParceledListSlice<T extends Parcelable> implements Parcelable {
+ /*
+ * TODO get this number from somewhere else. For now set it to a quarter of
+ * the 1MB limit.
+ */
+ private static final int MAX_IPC_SIZE = 256 * 1024;
+
+ private Parcel mParcel;
+
+ private int mNumItems;
+
+ private boolean mIsLastSlice;
+
+ public ParceledListSlice() {
+ mParcel = Parcel.obtain();
+ }
+
+ private ParceledListSlice(Parcel p, int numItems, boolean lastSlice) {
+ mParcel = p;
+ mNumItems = numItems;
+ mIsLastSlice = lastSlice;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * Write this to another Parcel. Note that this discards the internal Parcel
+ * and should not be used anymore. This is so we can pass this to a Binder
+ * where we won't have a chance to call recycle on this.
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mNumItems);
+ dest.writeInt(mIsLastSlice ? 1 : 0);
+
+ if (mNumItems > 0) {
+ final int parcelSize = mParcel.dataSize();
+ dest.writeInt(parcelSize);
+ dest.appendFrom(mParcel, 0, parcelSize);
+ }
+
+ mNumItems = 0;
+ mParcel.recycle();
+ mParcel = null;
+ }
+
+ /**
+ * Appends a parcel to this list slice.
+ *
+ * @param item Parcelable item to append to this list slice
+ * @return true when the list slice is full and should not be appended to
+ * anymore
+ */
+ public boolean append(T item) {
+ if (mParcel == null) {
+ throw new IllegalStateException("ParceledListSlice has already been recycled");
+ }
+
+ item.writeToParcel(mParcel, PARCELABLE_WRITE_RETURN_VALUE);
+ mNumItems++;
+
+ return mParcel.dataSize() > MAX_IPC_SIZE;
+ }
+
+ /**
+ * Populates a list and discards the internal state of the
+ * ParceledListSlice in the process. The instance should
+ * not be used anymore.
+ *
+ * @param list list to insert items from this slice.
+ * @param creator creator that knows how to unparcel the
+ * target object type.
+ * @return the last item inserted into the list or null if none.
+ */
+ public T populateList(List<T> list, Creator<T> creator) {
+ mParcel.setDataPosition(0);
+
+ T item = null;
+ for (int i = 0; i < mNumItems; i++) {
+ item = creator.createFromParcel(mParcel);
+ list.add(item);
+ }
+
+ mParcel.recycle();
+ mParcel = null;
+
+ return item;
+ }
+
+ /**
+ * Sets whether this is the last list slice in the series.
+ *
+ * @param lastSlice
+ */
+ public void setLastSlice(boolean lastSlice) {
+ mIsLastSlice = lastSlice;
+ }
+
+ /**
+ * Returns whether this is the last slice in a series of slices.
+ *
+ * @return true if this is the last slice in the series.
+ */
+ public boolean isLastSlice() {
+ return mIsLastSlice;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static final Parcelable.Creator<ParceledListSlice> CREATOR =
+ new Parcelable.Creator<ParceledListSlice>() {
+ public ParceledListSlice createFromParcel(Parcel in) {
+ final int numItems = in.readInt();
+ final boolean lastSlice = in.readInt() == 1;
+
+ if (numItems > 0) {
+ final int parcelSize = in.readInt();
+
+ // Advance within this Parcel
+ int offset = in.dataPosition();
+ in.setDataPosition(offset + parcelSize);
+
+ Parcel p = Parcel.obtain();
+ p.setDataPosition(0);
+ p.appendFrom(in, offset, parcelSize);
+ p.setDataPosition(0);
+
+ return new ParceledListSlice(p, numItems, lastSlice);
+ } else {
+ return new ParceledListSlice();
+ }
+ }
+
+ public ParceledListSlice[] newArray(int size) {
+ return new ParceledListSlice[size];
+ }
+ };
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index be67e96..931cb18 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -652,8 +652,8 @@ public final class AssetManager {
public native final void setConfiguration(int mcc, int mnc, String locale,
int orientation, int touchscreen, int density, int keyboard,
int keyboardHidden, int navigation, int screenWidth, int screenHeight,
- int screenWidthDp, int screenHeightDp, int screenLayout, int uiMode,
- int majorVersion);
+ int smallestScreenWidthDp, int screenWidthDp, int screenHeightDp,
+ int screenLayout, int uiMode, int majorVersion);
/**
* Retrieve the resource identifier for the given resource name.
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 0de08f2..12ec258 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -259,6 +259,15 @@ public final class Configuration implements Parcelable, Comparable<Configuration
*/
public int screenHeightDp;
+ public static final int SMALLEST_SCREEN_WIDTH_DP_UNDEFINED = 0;
+
+ /**
+ * The smallest screen size an application will see in normal operation.
+ * This is the smallest value of both screenWidthDp and screenHeightDp
+ * in both portrait and landscape.
+ */
+ public int smallestScreenWidthDp;
+
/**
* @hide Internal book-keeping.
*/
@@ -298,6 +307,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
uiMode = o.uiMode;
screenWidthDp = o.screenWidthDp;
screenHeightDp = o.screenHeightDp;
+ smallestScreenWidthDp = o.smallestScreenWidthDp;
seq = o.seq;
}
@@ -315,6 +325,56 @@ public final class Configuration implements Parcelable, Comparable<Configuration
} else {
sb.append(" (no locale)");
}
+ if (smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
+ sb.append(" sw"); sb.append(smallestScreenWidthDp); sb.append("dp");
+ } else {
+ sb.append("?swdp");
+ }
+ if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
+ sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
+ } else {
+ sb.append("?wdp");
+ }
+ if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
+ sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
+ } else {
+ sb.append("?hdp");
+ }
+ switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
+ case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
+ case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
+ case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
+ case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
+ case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
+ default: sb.append(" layoutSize=");
+ sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
+ }
+ switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
+ case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
+ case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
+ case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
+ default: sb.append(" layoutLong=");
+ sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
+ }
+ switch (orientation) {
+ case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
+ case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
+ case ORIENTATION_PORTRAIT: sb.append(" port"); break;
+ default: sb.append(" orien="); sb.append(orientation); break;
+ }
+ switch ((uiMode&UI_MODE_TYPE_MASK)) {
+ case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
+ case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
+ case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
+ case UI_MODE_TYPE_CAR: sb.append(" car"); break;
+ default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
+ }
+ switch ((uiMode&UI_MODE_NIGHT_MASK)) {
+ case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
+ case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
+ case UI_MODE_NIGHT_YES: sb.append(" night"); break;
+ default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
+ }
switch (touchscreen) {
case TOUCHSCREEN_UNDEFINED: sb.append(" ?touch"); break;
case TOUCHSCREEN_NOTOUCH: sb.append(" -touch"); break;
@@ -356,51 +416,6 @@ public final class Configuration implements Parcelable, Comparable<Configuration
case NAVIGATIONHIDDEN_YES: sb.append("/h"); break;
default: sb.append("/"); sb.append(navigationHidden); break;
}
- switch (orientation) {
- case ORIENTATION_UNDEFINED: sb.append(" ?orien"); break;
- case ORIENTATION_LANDSCAPE: sb.append(" land"); break;
- case ORIENTATION_PORTRAIT: sb.append(" port"); break;
- default: sb.append(" orien="); sb.append(orientation); break;
- }
- switch ((screenLayout&SCREENLAYOUT_SIZE_MASK)) {
- case SCREENLAYOUT_SIZE_UNDEFINED: sb.append(" ?lsize"); break;
- case SCREENLAYOUT_SIZE_SMALL: sb.append(" smll"); break;
- case SCREENLAYOUT_SIZE_NORMAL: sb.append(" nrml"); break;
- case SCREENLAYOUT_SIZE_LARGE: sb.append(" lrg"); break;
- case SCREENLAYOUT_SIZE_XLARGE: sb.append(" xlrg"); break;
- default: sb.append(" layoutSize=");
- sb.append(screenLayout&SCREENLAYOUT_SIZE_MASK); break;
- }
- switch ((screenLayout&SCREENLAYOUT_LONG_MASK)) {
- case SCREENLAYOUT_LONG_UNDEFINED: sb.append(" ?long"); break;
- case SCREENLAYOUT_LONG_NO: /* not-long is not interesting to print */ break;
- case SCREENLAYOUT_LONG_YES: sb.append(" long"); break;
- default: sb.append(" layoutLong=");
- sb.append(screenLayout&SCREENLAYOUT_LONG_MASK); break;
- }
- switch ((uiMode&UI_MODE_TYPE_MASK)) {
- case UI_MODE_TYPE_UNDEFINED: sb.append(" ?uimode"); break;
- case UI_MODE_TYPE_NORMAL: /* normal is not interesting to print */ break;
- case UI_MODE_TYPE_DESK: sb.append(" desk"); break;
- case UI_MODE_TYPE_CAR: sb.append(" car"); break;
- default: sb.append(" uimode="); sb.append(uiMode&UI_MODE_TYPE_MASK); break;
- }
- switch ((uiMode&UI_MODE_NIGHT_MASK)) {
- case UI_MODE_NIGHT_UNDEFINED: sb.append(" ?night"); break;
- case UI_MODE_NIGHT_NO: /* not-night is not interesting to print */ break;
- case UI_MODE_NIGHT_YES: sb.append(" night"); break;
- default: sb.append(" night="); sb.append(uiMode&UI_MODE_NIGHT_MASK); break;
- }
- if (screenWidthDp != SCREEN_WIDTH_DP_UNDEFINED) {
- sb.append(" w"); sb.append(screenWidthDp); sb.append("dp");
- } else {
- sb.append("?wdp");
- }
- if (screenHeightDp != SCREEN_HEIGHT_DP_UNDEFINED) {
- sb.append(" h"); sb.append(screenHeightDp); sb.append("dp");
- } else {
- sb.append("?hdp");
- }
if (seq != 0) {
sb.append(" s.");
sb.append(seq);
@@ -428,6 +443,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
uiMode = UI_MODE_TYPE_UNDEFINED;
screenWidthDp = SCREEN_WIDTH_DP_UNDEFINED;
screenHeightDp = SCREEN_HEIGHT_DP_UNDEFINED;
+ smallestScreenWidthDp = SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
seq = 0;
}
@@ -531,6 +547,11 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
screenHeightDp = delta.screenHeightDp;
}
+ if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+ && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+ changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+ smallestScreenWidthDp = delta.smallestScreenWidthDp;
+ }
if (delta.seq != 0) {
seq = delta.seq;
@@ -564,7 +585,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
* {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_LAYOUT
* PackageManager.ActivityInfo.CONFIG_SCREEN_LAYOUT}, or
* {@link android.content.pm.ActivityInfo#CONFIG_SCREEN_SIZE
- * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}.
+ * PackageManager.ActivityInfo.CONFIG_SCREEN_SIZE}, or
+ * {@link android.content.pm.ActivityInfo#CONFIG_SMALLEST_SCREEN_SIZE
+ * PackageManager.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE}.
*/
public int diff(Configuration delta) {
int changed = 0;
@@ -625,6 +648,10 @@ public final class Configuration implements Parcelable, Comparable<Configuration
&& screenHeightDp != delta.screenHeightDp) {
changed |= ActivityInfo.CONFIG_SCREEN_SIZE;
}
+ if (delta.smallestScreenWidthDp != SMALLEST_SCREEN_WIDTH_DP_UNDEFINED
+ && smallestScreenWidthDp != delta.smallestScreenWidthDp) {
+ changed |= ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
+ }
return changed;
}
@@ -708,6 +735,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
dest.writeInt(uiMode);
dest.writeInt(screenWidthDp);
dest.writeInt(screenHeightDp);
+ dest.writeInt(smallestScreenWidthDp);
dest.writeInt(seq);
}
@@ -731,6 +759,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
uiMode = source.readInt();
screenWidthDp = source.readInt();
screenHeightDp = source.readInt();
+ smallestScreenWidthDp = source.readInt();
seq = source.readInt();
}
@@ -795,6 +824,8 @@ public final class Configuration implements Parcelable, Comparable<Configuration
n = this.screenWidthDp - that.screenWidthDp;
if (n != 0) return n;
n = this.screenHeightDp - that.screenHeightDp;
+ if (n != 0) return n;
+ n = this.smallestScreenWidthDp - that.smallestScreenWidthDp;
//if (n != 0) return n;
return n;
}
@@ -830,6 +861,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
result = 31 * result + uiMode;
result = 31 * result + screenWidthDp;
result = 31 * result + screenHeightDp;
+ result = 31 * result + smallestScreenWidthDp;
return result;
}
}
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 540f704..a072e94 100755
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -1458,6 +1458,7 @@ public class Resources {
mConfiguration.touchscreen,
(int)(mMetrics.density*160), mConfiguration.keyboard,
keyboardHidden, mConfiguration.navigation, width, height,
+ mConfiguration.smallestScreenWidthDp,
mConfiguration.screenWidthDp, mConfiguration.screenHeightDp,
mConfiguration.screenLayout, mConfiguration.uiMode,
Build.VERSION.RESOURCES_SDK_INT);
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 6d955e7..d5c4ace 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -1181,6 +1181,8 @@ public class Camera {
private static final String KEY_EXPOSURE_COMPENSATION_STEP = "exposure-compensation-step";
private static final String KEY_AUTO_EXPOSURE_LOCK = "auto-exposure-lock";
private static final String KEY_AUTO_EXPOSURE_LOCK_SUPPORTED = "auto-exposure-lock-supported";
+ private static final String KEY_AUTO_WHITEBALANCE_LOCK = "auto-whitebalance-lock";
+ private static final String KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED = "auto-whitebalance-lock-supported";
private static final String KEY_METERING_AREAS = "metering-areas";
private static final String KEY_MAX_NUM_METERING_AREAS = "max-num-metering-areas";
private static final String KEY_ZOOM = "zoom";
@@ -2468,37 +2470,47 @@ public class Camera {
}
/**
- * Sets the auto-exposure lock state. Applications should check
- * {@link #isAutoExposureLockSupported} before using this method.
+ * <p>Sets the auto-exposure lock state. Applications should check
+ * {@link #isAutoExposureLockSupported} before using this method.</p>
*
- * If set to true, the camera auto-exposure routine will pause until the
- * lock is set to false. Exposure compensation settings changes will
- * still take effect while auto-exposure is locked. Stopping preview
- * with {@link #stopPreview()}, or triggering still image capture with
- * {@link #takePicture(Camera.ShutterCallback, Camera.PictureCallback,
- * Camera.PictureCallback)}, will automatically set the lock to
- * false. However, the lock can be re-enabled before preview is
- * re-started to keep the same AE parameters. Exposure compensation, in
- * conjunction with re-enabling the AE lock after each still capture,
- * can be used to capture an exposure-bracketed burst of images, for
- * example. Auto-exposure state, including the lock state, will not be
+ * <p>If set to true, the camera auto-exposure routine will immediately
+ * pause until the lock is set to false. Exposure compensation settings
+ * changes will still take effect while auto-exposure is locked.</p>
+ *
+ * <p>If auto-exposure is already locked, setting this to true again has
+ * no effect (the driver will not recalculate exposure values).</p>
+ *
+ * <p>Stopping preview with {@link #stopPreview()}, or triggering still
+ * image capture with {@link #takePicture(Camera.ShutterCallback,
+ * Camera.PictureCallback, Camera.PictureCallback)}, will automatically
+ * set the lock to false. However, the lock can be re-enabled before
+ * preview is re-started to keep the same AE parameters.</p>
+ *
+ * <p>Exposure compensation, in conjunction with re-enabling the AE and
+ * AWB locks after each still capture, can be used to capture an
+ * exposure-bracketed burst of images, for example.</p>
+ *
+ * <p>Auto-exposure state, including the lock state, will not be
* maintained after camera {@link #release()} is called. Locking
* auto-exposure after {@link #open()} but before the first call to
* {@link #startPreview()} will not allow the auto-exposure routine to
- * run at all, and may result in severely over- or under-exposed images.
+ * run at all, and may result in severely over- or under-exposed
+ * images.</p>
*
- * The driver may also independently lock auto-exposure after auto-focus
- * completes. If this is undesirable, be sure to always set the
- * auto-exposure lock to false after the
+ * <p>The driver may also independently lock auto-exposure after
+ * auto-focus completes. If this is undesirable, be sure to always set
+ * the auto-exposure lock to false after the
* {@link AutoFocusCallback#onAutoFocus(boolean, Camera)} callback is
* received. The {@link #getAutoExposureLock()} method can be used after
* the callback to determine if the camera has locked auto-exposure
- * independently.
+ * independently.</p>
*
* @param toggle new state of the auto-exposure lock. True means that
* auto-exposure is locked, false means that the auto-exposure
* routine is free to run normally.
*
+ * @see #getAutoExposureLock()
+ *
* @hide
*/
public void setAutoExposureLock(boolean toggle) {
@@ -2542,6 +2554,91 @@ public class Camera {
}
/**
+ * <p>Sets the auto-white balance lock state. Applications should check
+ * {@link #isAutoWhiteBalanceLockSupported} before using this
+ * method.</p>
+ *
+ * <p>If set to true, the camera auto-white balance routine will
+ * immediately pause until the lock is set to false.</p>
+ *
+ * <p>If auto-white balance is already locked, setting this to true
+ * again has no effect (the driver will not recalculate white balance
+ * values).</p>
+ *
+ * <p>Stopping preview with {@link #stopPreview()}, or triggering still
+ * image capture with {@link #takePicture(Camera.ShutterCallback,
+ * Camera.PictureCallback, Camera.PictureCallback)}, will automatically
+ * set the lock to false. However, the lock can be re-enabled before
+ * preview is re-started to keep the same white balance parameters.</p>
+ *
+ * <p>Exposure compensation, in conjunction with re-enabling the AE and
+ * AWB locks after each still capture, can be used to capture an
+ * exposure-bracketed burst of images, for example. Auto-white balance
+ * state, including the lock state, will not be maintained after camera
+ * {@link #release()} is called. Locking auto-white balance after
+ * {@link #open()} but before the first call to {@link #startPreview()}
+ * will not allow the auto-white balance routine to run at all, and may
+ * result in severely incorrect color in captured images.</p>
+ *
+ * <p>The driver may also independently lock auto-white balance after
+ * auto-focus completes. If this is undesirable, be sure to always set
+ * the auto-white balance lock to false after the
+ * {@link AutoFocusCallback#onAutoFocus(boolean, Camera)} callback is
+ * received. The {@link #getAutoWhiteBalanceLock()} method can be used
+ * after the callback to determine if the camera has locked auto-white
+ * balance independently.</p>
+ *
+ * @param toggle new state of the auto-white balance lock. True means
+ * that auto-white balance is locked, false means that the
+ * auto-white balance routine is free to run normally.
+ *
+ * @see #getAutoWhiteBalanceLock()
+ *
+ * @hide
+ */
+ public void setAutoWhiteBalanceLock(boolean toggle) {
+ set(KEY_AUTO_WHITEBALANCE_LOCK, toggle ? TRUE : FALSE);
+ }
+
+ /**
+ * Gets the state of the auto-white balance lock. Applications should
+ * check {@link #isAutoWhiteBalanceLockSupported} before using this
+ * method. See {@link #setAutoWhiteBalanceLock} for details about the
+ * lock.
+ *
+ * @return State of the auto-white balance lock. Returns true if
+ * auto-white balance is currently locked, and false
+ * otherwise. The auto-white balance lock may be independently
+ * enabled by the camera subsystem when auto-focus has
+ * completed. This method can be used after the
+ * {@link AutoFocusCallback#onAutoFocus(boolean, Camera)}
+ * callback to determine if the camera has locked AWB.
+ *
+ * @see #setAutoWhiteBalanceLock(boolean)
+ *
+ * @hide
+ */
+ public boolean getAutoWhiteBalanceLock() {
+ String str = get(KEY_AUTO_WHITEBALANCE_LOCK);
+ return TRUE.equals(str);
+ }
+
+ /**
+ * Returns true if auto-white balance locking is supported. Applications
+ * should call this before trying to lock auto-white balance. See
+ * {@link #setAutoWhiteBalanceLock} for details about the lock.
+ *
+ * @return true if auto-white balance lock is supported.
+ * @see #setAutoWhiteBalanceLock(boolean)
+ *
+ * @hide
+ */
+ public boolean isAutoWhiteBalanceLockSupported() {
+ String str = get(KEY_AUTO_WHITEBALANCE_LOCK_SUPPORTED);
+ return TRUE.equals(str);
+ }
+
+ /**
* Gets current zoom value. This also works when smooth zoom is in
* progress. Applications should check {@link #isZoomSupported} before
* using this method.
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index a4ba3bd..68fc101 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -104,6 +104,13 @@ public class Sensor {
*/
public static final int TYPE_ROTATION_VECTOR = 11;
+ /**
+ * A constant describing a relative humidity sensor type.
+ * See {@link android.hardware.SensorEvent SensorEvent}
+ * for more details.
+ */
+ public static final int TYPE_RELATIVE_HUMIDITY = 12;
+
/** A constant describing an ambient temperature sensor type */
public static final int TYPE_AMBIENT_TEMPERATURE = 13;
diff --git a/core/java/android/hardware/SensorEvent.java b/core/java/android/hardware/SensorEvent.java
index b111b84..0411b5c 100644
--- a/core/java/android/hardware/SensorEvent.java
+++ b/core/java/android/hardware/SensorEvent.java
@@ -327,6 +327,64 @@ public class SensorEvent {
* in the clockwise direction (mathematically speaking, it should be
* positive in the counter-clockwise direction).
* </p>
+ *
+ * <h4>{@link android.hardware.Sensor#TYPE_RELATIVE_HUMIDITY
+ * Sensor.TYPE_RELATIVE_HUMIDITY}:</h4>
+ * <ul>
+ * <p>
+ * values[0]: Relative ambient air humidity in percent
+ * </p>
+ * </ul>
+ * <p>
+ * When relative ambient air humidity and ambient temperature are
+ * measured, the dew point and absolute humidity can be calculated.
+ * </p>
+ * <u>Dew Point</u>
+ * <p>
+ * The dew point is the temperature to which a given parcel of air must be
+ * cooled, at constant barometric pressure, for water vapor to condense
+ * into water.
+ * </p>
+ * <center><pre>
+ * ln(RH/100%) + m&#183;t/(T<sub>n</sub>+t)
+ * t<sub>d</sub>(t,RH) = T<sub>n</sub> &#183; ------------------------------
+ * m - [ln(RH/100%) + m&#183;t/(T<sub>n</sub>+t)]
+ * </pre></center>
+ * <dl>
+ * <dt>t<sub>d</sub></dt> <dd>dew point temperature in &deg;C</dd>
+ * <dt>t</dt> <dd>actual temperature in &deg;C</dd>
+ * <dt>RH</dt> <dd>actual relative humidity in %</dd>
+ * <dt>m</dt> <dd>17.62</dd>
+ * <dt>T<sub>n</sub></dt> <dd>243.12 &deg;C</dd>
+ * </dl>
+ * <p>for example:</p>
+ * <pre class="prettyprint">
+ * h = Math.log(rh / 100.0) + (17.62 * t) / (243.12 + t);
+ * td = 243.12 * h / (17.62 - h);
+ * </pre>
+ * <u>Absolute Humidity</u>
+ * <p>
+ * The absolute humidity is the mass of water vapor in a particular volume
+ * of dry air. The unit is g/m<sup>3</sup>.
+ * </p>
+ * <center><pre>
+ * RH/100%&#183;A&#183;exp(m&#183;t/(T<sub>n</sub>+t))
+ * d<sub>v</sub>(t,RH) = 216.7 &#183; -------------------------
+ * 273.15 + t
+ * </pre></center>
+ * <dl>
+ * <dt>d<sub>v</sub></dt> <dd>absolute humidity in g/m<sup>3</sup></dd>
+ * <dt>t</dt> <dd>actual temperature in &deg;C</dd>
+ * <dt>RH</dt> <dd>actual relative humidity in %</dd>
+ * <dt>m</dt> <dd>17.62</dd>
+ * <dt>T<sub>n</sub></dt> <dd>243.12 &deg;C</dd>
+ * <dt>A</dt> <dd>6.112 hPa</dd>
+ * </dl>
+ * <p>for example:</p>
+ * <pre class="prettyprint">
+ * dv = 216.7 *
+ * (rh / 100.0 * 6.112 * Math.exp(17.62 * t / (243.12 + t)) / (273.15 + t));
+ * </pre>
*
* <h4>{@link android.hardware.Sensor#TYPE_AMBIENT_TEMPERATURE Sensor.TYPE_AMBIENT_TEMPERATURE}:
* </h4>
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
index a153c0b..b536490 100644
--- a/core/java/android/hardware/usb/UsbDeviceConnection.java
+++ b/core/java/android/hardware/usb/UsbDeviceConnection.java
@@ -69,6 +69,17 @@ public class UsbDeviceConnection {
}
/**
+ * Returns the raw USB descriptors for the device.
+ * This can be used to access descriptors not supported directly
+ * via the higher level APIs.
+ *
+ * @return raw USB descriptors
+ */
+ public byte[] getRawDescriptors() {
+ return native_get_desc();
+ }
+
+ /**
* Claims exclusive access to a {@link android.hardware.usb.UsbInterface}.
* This must be done before sending or receiving data on any
* {@link android.hardware.usb.UsbEndpoint}s belonging to the interface.
@@ -160,6 +171,7 @@ public class UsbDeviceConnection {
private native boolean native_open(String deviceName, FileDescriptor pfd);
private native void native_close();
private native int native_get_fd();
+ private native byte[] native_get_desc();
private native boolean native_claim_interface(int interfaceID, boolean force);
private native boolean native_release_interface(int interfaceID);
private native int native_control_request(int requestType, int request, int value,
diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl
new file mode 100644
index 0000000..fa6eae5
--- /dev/null
+++ b/core/java/android/net/INetworkPolicyManager.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+/**
+ * Interface that creates and modifies network policy rules.
+ *
+ * {@hide}
+ */
+interface INetworkPolicyManager {
+
+ void onForegroundActivitiesChanged(int uid, int pid, boolean foregroundActivities);
+ void onProcessDied(int uid, int pid);
+
+ void setUidPolicy(int uid, int policy);
+ int getUidPolicy(int uid);
+
+ // TODO: build API to surface stats details for settings UI
+
+}
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 61acf2b..19894a0 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -68,7 +68,8 @@ public class LinkProperties implements Parcelable {
mLinkAddresses = source.getLinkAddresses();
mDnses = source.getDnses();
mRoutes = source.getRoutes();
- mHttpProxy = new ProxyProperties(source.getHttpProxy());
+ mHttpProxy = (source.getHttpProxy() == null) ?
+ null : new ProxyProperties(source.getHttpProxy());
}
}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index bb6ee0f..770f152 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -276,6 +276,21 @@ public class MobileDataStateTracker implements NetworkStateTracker {
setDetailedState(DetailedState.CONNECTED, reason, apnName);
break;
}
+ } else {
+ // There was no state change. Check if LinkProperties has been updated.
+ if (TextUtils.equals(reason, Phone.REASON_LINK_PROPERTIES_CHANGED)) {
+ mLinkProperties = intent.getParcelableExtra(Phone.DATA_LINK_PROPERTIES_KEY);
+ if (mLinkProperties == null) {
+ log("No link property in LINK_PROPERTIES change event.");
+ mLinkProperties = new LinkProperties();
+ }
+ // Just update reason field in this NetworkInfo
+ mNetworkInfo.setDetailedState(mNetworkInfo.getDetailedState(), reason,
+ mNetworkInfo.getExtraInfo());
+ Message msg = mTarget.obtainMessage(EVENT_CONFIGURATION_CHANGED,
+ mNetworkInfo);
+ msg.sendToTarget();
+ }
}
} else if (intent.getAction().
equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
new file mode 100644
index 0000000..2312bd9
--- /dev/null
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.os.RemoteException;
+
+/**
+ * Manager for creating and modifying network policy rules.
+ *
+ * {@hide}
+ */
+public class NetworkPolicyManager {
+
+ /** No specific network policy, use system default. */
+ public static final int POLICY_NONE = 0x0;
+ /** Reject network usage when application in background. */
+ public static final int POLICY_REJECT_BACKGROUND = 0x1;
+ /** Reject network usage on paid network connections. */
+ public static final int POLICY_REJECT_PAID = 0x2;
+ /** Application should conserve data. */
+ public static final int POLICY_CONSERVE_DATA = 0x4;
+
+ private INetworkPolicyManager mService;
+
+ public NetworkPolicyManager(INetworkPolicyManager service) {
+ if (service == null) {
+ throw new IllegalArgumentException("missing INetworkPolicyManager");
+ }
+ mService = service;
+ }
+
+ /**
+ * Set policy flags for specific UID.
+ *
+ * @param policy {@link #POLICY_NONE} or combination of
+ * {@link #POLICY_REJECT_BACKGROUND}, {@link #POLICY_REJECT_PAID},
+ * or {@link #POLICY_CONSERVE_DATA}.
+ */
+ public void setUidPolicy(int uid, int policy) {
+ try {
+ mService.setUidPolicy(uid, policy);
+ } catch (RemoteException e) {
+ }
+ }
+
+ public int getUidPolicy(int uid) {
+ try {
+ return mService.getUidPolicy(uid);
+ } catch (RemoteException e) {
+ return POLICY_NONE;
+ }
+ }
+
+}
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index fbe5379..8a678d6 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -38,32 +38,6 @@ public class NetworkUtils {
/** Bring the named network interface down. */
public native static int disableInterface(String interfaceName);
- /**
- * Add a route to the routing table.
- *
- * @param interfaceName the interface to route through.
- * @param dst the network or host to route to. May be IPv4 or IPv6, e.g.
- * "0.0.0.0" or "2001:4860::".
- * @param prefixLength the prefix length of the route.
- * @param gw the gateway to use, e.g., "192.168.251.1". If null,
- * indicates a directly-connected route.
- */
- public native static int addRoute(String interfaceName, String dst,
- int prefixLength, String gw);
-
- /** Return the gateway address for the default route for the named interface. */
- public static InetAddress getDefaultRoute(String interfaceName) {
- int addr = getDefaultRouteNative(interfaceName);
- return intToInetAddress(addr);
- }
- private native static int getDefaultRouteNative(String interfaceName);
-
- /** Remove host routes that uses the named interface. */
- public native static int removeHostRoutes(String interfaceName);
-
- /** Remove the default route for the named interface. */
- public native static int removeDefaultRoute(String interfaceName);
-
/** Reset any sockets that are connected via the named interface. */
public native static int resetConnections(String interfaceName);
@@ -160,6 +134,15 @@ public class NetworkUtils {
}
/**
+ * Convert a IPv4 netmask integer to a prefix length
+ * @param netmask as an integer in network byte order
+ * @return the network prefix length
+ */
+ public static int netmaskIntToPrefixLength(int netmask) {
+ return Integer.bitCount(netmask);
+ }
+
+ /**
* Create an InetAddress from a string where the string must be a standard
* representation of a V4 or V6 address. Avoids doing a DNS lookup on failure
* but it will throw an IllegalArgumentException in that case.
@@ -173,60 +156,6 @@ public class NetworkUtils {
}
/**
- * Add a default route through the specified gateway.
- * @param interfaceName interface on which the route should be added
- * @param gw the IP address of the gateway to which the route is desired,
- * @return {@code true} on success, {@code false} on failure
- */
- public static boolean addDefaultRoute(String interfaceName, InetAddress gw) {
- String dstStr;
- String gwStr = gw.getHostAddress();
-
- if (gw instanceof Inet4Address) {
- dstStr = "0.0.0.0";
- } else if (gw instanceof Inet6Address) {
- dstStr = "::";
- } else {
- Log.w(TAG, "addDefaultRoute failure: address is neither IPv4 nor IPv6" +
- "(" + gwStr + ")");
- return false;
- }
- return addRoute(interfaceName, dstStr, 0, gwStr) == 0;
- }
-
- /**
- * Add a host route.
- * @param interfaceName interface on which the route should be added
- * @param dst the IP address of the host to which the route is desired,
- * this should not be null.
- * @param gw the IP address of the gateway to which the route is desired,
- * if null, indicates a directly-connected route.
- * @return {@code true} on success, {@code false} on failure
- */
- public static boolean addHostRoute(String interfaceName, InetAddress dst,
- InetAddress gw) {
- if (dst == null) {
- Log.w(TAG, "addHostRoute: dst should not be null");
- return false;
- }
-
- int prefixLength;
- String dstStr = dst.getHostAddress();
- String gwStr = (gw != null) ? gw.getHostAddress() : null;
-
- if (dst instanceof Inet4Address) {
- prefixLength = 32;
- } else if (dst instanceof Inet6Address) {
- prefixLength = 128;
- } else {
- Log.w(TAG, "addHostRoute failure: address is neither IPv4 nor IPv6" +
- "(" + dst + ")");
- return false;
- }
- return addRoute(interfaceName, dstStr, prefixLength, gwStr) == 0;
- }
-
- /**
* Get InetAddress masked with prefixLength. Will never return null.
* @param IP address which will be masked with specified prefixLength
* @param prefixLength the prefixLength used to mask the IP
@@ -271,4 +200,25 @@ public class NetworkUtils {
return (((left instanceof Inet4Address) && (right instanceof Inet4Address)) ||
((left instanceof Inet6Address) && (right instanceof Inet6Address)));
}
+
+ /**
+ * Convert a 32 char hex string into a Inet6Address.
+ * throws a runtime exception if the string isn't 32 chars, isn't hex or can't be
+ * made into an Inet6Address
+ * @param addrHexString a 32 character hex string representing an IPv6 addr
+ * @return addr an InetAddress representation for the string
+ */
+ public static InetAddress hexToInet6Address(String addrHexString)
+ throws IllegalArgumentException {
+ try {
+ return numericToInetAddress(String.format("%s:%s:%s:%s:%s:%s:%s:%s",
+ addrHexString.substring(0,4), addrHexString.substring(4,8),
+ addrHexString.substring(8,12), addrHexString.substring(12,16),
+ addrHexString.substring(16,20), addrHexString.substring(20,24),
+ addrHexString.substring(24,28), addrHexString.substring(28,32)));
+ } catch (Exception e) {
+ Log.e("NetworkUtils", "error in hexToInet6Address(" + addrHexString + "): " + e);
+ throw new IllegalArgumentException(e);
+ }
+ }
}
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 39e708a..8e5ddda 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -46,18 +46,16 @@ public class RouteInfo implements Parcelable {
public RouteInfo(LinkAddress destination, InetAddress gateway) {
if (destination == null) {
- try {
- if (gateway != null) {
- if (gateway instanceof Inet4Address) {
- destination = new LinkAddress(Inet4Address.ANY, 0);
- } else {
- destination = new LinkAddress(Inet6Address.ANY, 0);
- }
+ if (gateway != null) {
+ if (gateway instanceof Inet4Address) {
+ destination = new LinkAddress(Inet4Address.ANY, 0);
} else {
- // no destination, no gateway. invalid.
- throw new RuntimeException("Invalid arguments passed in.");
+ destination = new LinkAddress(Inet6Address.ANY, 0);
}
- } catch (Exception e) {}
+ } else {
+ // no destination, no gateway. invalid.
+ throw new RuntimeException("Invalid arguments passed in.");
+ }
}
if (gateway == null) {
if (destination.getAddress() instanceof Inet4Address) {
@@ -76,6 +74,20 @@ public class RouteInfo implements Parcelable {
this(null, gateway);
}
+ public static RouteInfo makeHostRoute(InetAddress host) {
+ return makeHostRoute(host, null);
+ }
+
+ public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway) {
+ if (host == null) return null;
+
+ if (host instanceof Inet4Address) {
+ return new RouteInfo(new LinkAddress(host, 32), gateway);
+ } else {
+ return new RouteInfo(new LinkAddress(host, 128), gateway);
+ }
+ }
+
private boolean isDefault() {
boolean val = false;
if (mGateway != null) {
@@ -128,6 +140,33 @@ public class RouteInfo implements Parcelable {
}
}
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+
+ if (!(obj instanceof RouteInfo)) return false;
+
+ RouteInfo target = (RouteInfo) obj;
+
+ boolean sameDestination = ( mDestination == null) ?
+ target.getDestination() == null
+ : mDestination.equals(target.getDestination());
+
+ boolean sameAddress = (mGateway == null) ?
+ target.getGateway() == null
+ : mGateway.equals(target.getGateway());
+
+ return sameDestination && sameAddress
+ && mIsDefault == target.mIsDefault;
+ }
+
+ @Override
+ public int hashCode() {
+ return (mDestination == null ? 0 : mDestination.hashCode())
+ + (mGateway == null ? 0 :mGateway.hashCode())
+ + (mIsDefault ? 3 : 7);
+ }
+
public static final Creator<RouteInfo> CREATOR =
new Creator<RouteInfo>() {
public RouteInfo createFromParcel(Parcel in) {
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index fe36786..ecc111b 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -20,6 +20,7 @@ package android.os;
import android.net.InterfaceConfiguration;
import android.net.INetworkManagementEventObserver;
import android.net.NetworkStats;
+import android.net.RouteInfo;
import android.net.wifi.WifiConfiguration;
/**
@@ -58,6 +59,22 @@ interface INetworkManagementService
void setInterfaceConfig(String iface, in InterfaceConfiguration cfg);
/**
+ * Retrieves the network routes currently configured on the specified
+ * interface
+ */
+ RouteInfo[] getRoutes(String iface);
+
+ /**
+ * Add the specified route to the interface.
+ */
+ void addRoute(String iface, in RouteInfo route);
+
+ /**
+ * Remove the specified route from the interface.
+ */
+ void removeRoute(String iface, in RouteInfo route);
+
+ /**
* Shuts down the service
*/
void shutdown();
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index d79f6c8..d68e6fb 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -34,10 +34,10 @@ public class StorageVolume implements Parcelable {
private final boolean mRemovable;
private final boolean mEmulated;
private final int mMtpReserveSpace;
+ private int mStorageId;
public StorageVolume(String path, String description,
- boolean removable, boolean emulated,
- int mtpReserveSpace) {
+ boolean removable, boolean emulated, int mtpReserveSpace) {
mPath = path;
mDescription = description;
mRemovable = removable;
@@ -45,6 +45,17 @@ public class StorageVolume implements Parcelable {
mMtpReserveSpace = mtpReserveSpace;
}
+ // for parcelling only
+ private StorageVolume(String path, String description,
+ boolean removable, boolean emulated, int mtpReserveSpace, int storageId) {
+ mPath = path;
+ mDescription = description;
+ mRemovable = removable;
+ mEmulated = emulated;
+ mMtpReserveSpace = mtpReserveSpace;
+ mStorageId = storageId;
+ }
+
/**
* Returns the mount path for the volume.
*
@@ -82,6 +93,25 @@ public class StorageVolume implements Parcelable {
}
/**
+ * Returns the MTP storage ID for the volume.
+ * this is also used for the storage_id column in the media provider.
+ *
+ * @return MTP storage ID
+ */
+ public int getStorageId() {
+ return mStorageId;
+ }
+
+ /**
+ * Do not call this unless you are MountService
+ */
+ public void setStorageId(int index) {
+ // storage ID is 0x00010001 for primary storage,
+ // then 0x00020001, 0x00030001, etc. for secondary storages
+ mStorageId = ((index + 1) << 16) + 1;
+ }
+
+ /**
* Number of megabytes of space to leave unallocated by MTP.
* MTP will subtract this value from the free space it reports back
* to the host via GetStorageInfo, and will not allow new files to
@@ -123,9 +153,11 @@ public class StorageVolume implements Parcelable {
String description = in.readString();
int removable = in.readInt();
int emulated = in.readInt();
+ int storageId = in.readInt();
int mtpReserveSpace = in.readInt();
return new StorageVolume(path, description,
- removable == 1, emulated == 1, mtpReserveSpace);
+ removable == 1, emulated == 1,
+ mtpReserveSpace, storageId);
}
public StorageVolume[] newArray(int size) {
@@ -142,6 +174,7 @@ public class StorageVolume implements Parcelable {
parcel.writeString(mDescription);
parcel.writeInt(mRemovable ? 1 : 0);
parcel.writeInt(mEmulated ? 1 : 0);
+ parcel.writeInt(mStorageId);
parcel.writeInt(mMtpReserveSpace);
}
}
diff --git a/core/java/android/server/BluetoothInputProfileHandler.java b/core/java/android/server/BluetoothInputProfileHandler.java
index e6513fd..247e297 100644
--- a/core/java/android/server/BluetoothInputProfileHandler.java
+++ b/core/java/android/server/BluetoothInputProfileHandler.java
@@ -60,7 +60,7 @@ final class BluetoothInputProfileHandler {
return sInstance;
}
- synchronized boolean connectInputDevice(BluetoothDevice device,
+ boolean connectInputDevice(BluetoothDevice device,
BluetoothDeviceProfileState state) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (objectPath == null ||
@@ -78,7 +78,7 @@ final class BluetoothInputProfileHandler {
return false;
}
- synchronized boolean connectInputDeviceInternal(BluetoothDevice device) {
+ boolean connectInputDeviceInternal(BluetoothDevice device) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_CONNECTING);
if (!mBluetoothService.connectInputDeviceNative(objectPath)) {
@@ -88,7 +88,7 @@ final class BluetoothInputProfileHandler {
return true;
}
- synchronized boolean disconnectInputDevice(BluetoothDevice device,
+ boolean disconnectInputDevice(BluetoothDevice device,
BluetoothDeviceProfileState state) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (objectPath == null ||
@@ -105,7 +105,7 @@ final class BluetoothInputProfileHandler {
return false;
}
- synchronized boolean disconnectInputDeviceInternal(BluetoothDevice device) {
+ boolean disconnectInputDeviceInternal(BluetoothDevice device) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
handleInputDeviceStateChange(device, BluetoothInputDevice.STATE_DISCONNECTING);
if (!mBluetoothService.disconnectInputDeviceNative(objectPath)) {
@@ -115,31 +115,31 @@ final class BluetoothInputProfileHandler {
return true;
}
- synchronized int getInputDeviceConnectionState(BluetoothDevice device) {
+ int getInputDeviceConnectionState(BluetoothDevice device) {
if (mInputDevices.get(device) == null) {
return BluetoothInputDevice.STATE_DISCONNECTED;
}
return mInputDevices.get(device);
}
- synchronized List<BluetoothDevice> getConnectedInputDevices() {
+ List<BluetoothDevice> getConnectedInputDevices() {
List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(
new int[] {BluetoothInputDevice.STATE_CONNECTED});
return devices;
}
- synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates(int[] states) {
+ List<BluetoothDevice> getInputDevicesMatchingConnectionStates(int[] states) {
List<BluetoothDevice> devices = lookupInputDevicesMatchingStates(states);
return devices;
}
- synchronized int getInputDevicePriority(BluetoothDevice device) {
+ int getInputDevicePriority(BluetoothDevice device) {
return Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.getBluetoothInputDevicePriorityKey(device.getAddress()),
BluetoothInputDevice.PRIORITY_UNDEFINED);
}
- synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) {
+ boolean setInputDevicePriority(BluetoothDevice device, int priority) {
if (!BluetoothAdapter.checkBluetoothAddress(device.getAddress())) {
return false;
}
@@ -148,7 +148,7 @@ final class BluetoothInputProfileHandler {
priority);
}
- synchronized List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
+ List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
List<BluetoothDevice> inputDevices = new ArrayList<BluetoothDevice>();
for (BluetoothDevice device: mInputDevices.keySet()) {
@@ -163,7 +163,7 @@ final class BluetoothInputProfileHandler {
return inputDevices;
}
- private synchronized void handleInputDeviceStateChange(BluetoothDevice device, int state) {
+ private void handleInputDeviceStateChange(BluetoothDevice device, int state) {
int prevState;
if (mInputDevices.get(device) == null) {
prevState = BluetoothInputDevice.STATE_DISCONNECTED;
@@ -194,7 +194,7 @@ final class BluetoothInputProfileHandler {
mBluetoothService.sendConnectionStateChange(device, state, prevState);
}
- synchronized void handleInputDevicePropertyChange(String address, boolean connected) {
+ void handleInputDevicePropertyChange(String address, boolean connected) {
int state = connected ? BluetoothInputDevice.STATE_CONNECTED :
BluetoothInputDevice.STATE_DISCONNECTED;
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
@@ -202,7 +202,7 @@ final class BluetoothInputProfileHandler {
handleInputDeviceStateChange(device, state);
}
- synchronized void setInitialInputDevicePriority(BluetoothDevice device, int state) {
+ void setInitialInputDevicePriority(BluetoothDevice device, int state) {
switch (state) {
case BluetoothDevice.BOND_BONDED:
if (getInputDevicePriority(device) == BluetoothInputDevice.PRIORITY_UNDEFINED) {
diff --git a/core/java/android/server/BluetoothPanProfileHandler.java b/core/java/android/server/BluetoothPanProfileHandler.java
index 8925856..0d63e19 100644
--- a/core/java/android/server/BluetoothPanProfileHandler.java
+++ b/core/java/android/server/BluetoothPanProfileHandler.java
@@ -76,17 +76,17 @@ final class BluetoothPanProfileHandler {
}
}
- static synchronized BluetoothPanProfileHandler getInstance(Context context,
+ static BluetoothPanProfileHandler getInstance(Context context,
BluetoothService service) {
if (sInstance == null) sInstance = new BluetoothPanProfileHandler(context, service);
return sInstance;
}
- synchronized boolean isTetheringOn() {
+ boolean isTetheringOn() {
return mTetheringOn;
}
- synchronized boolean allowIncomingTethering() {
+ boolean allowIncomingTethering() {
if (isTetheringOn() && getConnectedPanDevices().size() < mMaxPanDevices)
return true;
return false;
@@ -94,7 +94,7 @@ final class BluetoothPanProfileHandler {
private BroadcastReceiver mTetheringReceiver = null;
- synchronized void setBluetoothTethering(boolean value) {
+ void setBluetoothTethering(boolean value) {
if (!value) {
disconnectPanServerDevices();
}
@@ -104,7 +104,7 @@ final class BluetoothPanProfileHandler {
filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
mTetheringReceiver = new BroadcastReceiver() {
@Override
- public synchronized void onReceive(Context context, Intent intent) {
+ public void onReceive(Context context, Intent intent) {
if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF)
== BluetoothAdapter.STATE_ON) {
mTetheringOn = true;
@@ -118,7 +118,7 @@ final class BluetoothPanProfileHandler {
}
}
- synchronized int getPanDeviceConnectionState(BluetoothDevice device) {
+ int getPanDeviceConnectionState(BluetoothDevice device) {
BluetoothPanDevice panDevice = mPanDevices.get(device);
if (panDevice == null) {
return BluetoothPan.STATE_DISCONNECTED;
@@ -126,7 +126,7 @@ final class BluetoothPanProfileHandler {
return panDevice.mState;
}
- synchronized boolean connectPanDevice(BluetoothDevice device) {
+ boolean connectPanDevice(BluetoothDevice device) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
if (DBG) Log.d(TAG, "connect PAN(" + objectPath + ")");
if (getPanDeviceConnectionState(device) != BluetoothPan.STATE_DISCONNECTED) {
@@ -158,7 +158,7 @@ final class BluetoothPanProfileHandler {
}
}
- private synchronized boolean disconnectPanServerDevices() {
+ private boolean disconnectPanServerDevices() {
debugLog("disconnect all PAN devices");
for (BluetoothDevice device: mPanDevices.keySet()) {
@@ -187,7 +187,7 @@ final class BluetoothPanProfileHandler {
return true;
}
- synchronized List<BluetoothDevice> getConnectedPanDevices() {
+ List<BluetoothDevice> getConnectedPanDevices() {
List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
for (BluetoothDevice device: mPanDevices.keySet()) {
@@ -198,7 +198,7 @@ final class BluetoothPanProfileHandler {
return devices;
}
- synchronized List<BluetoothDevice> getPanDevicesMatchingConnectionStates(int[] states) {
+ List<BluetoothDevice> getPanDevicesMatchingConnectionStates(int[] states) {
List<BluetoothDevice> devices = new ArrayList<BluetoothDevice>();
for (BluetoothDevice device: mPanDevices.keySet()) {
@@ -213,7 +213,7 @@ final class BluetoothPanProfileHandler {
return devices;
}
- synchronized boolean disconnectPanDevice(BluetoothDevice device) {
+ boolean disconnectPanDevice(BluetoothDevice device) {
String objectPath = mBluetoothService.getObjectPathFromAddress(device.getAddress());
debugLog("disconnect PAN(" + objectPath + ")");
@@ -249,7 +249,7 @@ final class BluetoothPanProfileHandler {
return true;
}
- synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+ void handlePanDeviceStateChange(BluetoothDevice device,
String iface, int state, int role) {
int prevState;
String ifaceAddr = null;
@@ -304,7 +304,7 @@ final class BluetoothPanProfileHandler {
mBluetoothService.sendConnectionStateChange(device, state, prevState);
}
- synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+ void handlePanDeviceStateChange(BluetoothDevice device,
int state, int role) {
handlePanDeviceStateChange(device, null, state, role);
}
@@ -343,7 +343,7 @@ final class BluetoothPanProfileHandler {
}
// configured when we start tethering
- private synchronized String enableTethering(String iface) {
+ private String enableTethering(String iface) {
debugLog("updateTetherState:" + iface);
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index f98d275..60bee9a 100644..100755
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -1104,7 +1104,7 @@ public class BluetoothService extends IBluetooth.Stub {
}
/*package*/ synchronized boolean setBondState(String address, int state, int reason) {
- mBondState.setBondState(address.toUpperCase(), state);
+ mBondState.setBondState(address.toUpperCase(), state, reason);
return true;
}
@@ -1928,120 +1928,163 @@ public class BluetoothService extends IBluetooth.Stub {
}
/**** Handlers for PAN Profile ****/
+ // TODO: This needs to be converted to a state machine.
- public synchronized boolean isTetheringOn() {
+ public boolean isTetheringOn() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothPanProfileHandler.isTetheringOn();
+ synchronized (mBluetoothPanProfileHandler) {
+ return mBluetoothPanProfileHandler.isTetheringOn();
+ }
}
- /*package*/ synchronized boolean allowIncomingTethering() {
- return mBluetoothPanProfileHandler.allowIncomingTethering();
+ /*package*/boolean allowIncomingTethering() {
+ synchronized (mBluetoothPanProfileHandler) {
+ return mBluetoothPanProfileHandler.allowIncomingTethering();
+ }
}
- public synchronized void setBluetoothTethering(boolean value) {
+ public void setBluetoothTethering(boolean value) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- mBluetoothPanProfileHandler.setBluetoothTethering(value);
+ synchronized (mBluetoothPanProfileHandler) {
+ mBluetoothPanProfileHandler.setBluetoothTethering(value);
+ }
}
- public synchronized int getPanDeviceConnectionState(BluetoothDevice device) {
+ public int getPanDeviceConnectionState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device);
+ synchronized (mBluetoothPanProfileHandler) {
+ return mBluetoothPanProfileHandler.getPanDeviceConnectionState(device);
+ }
}
- public synchronized boolean connectPanDevice(BluetoothDevice device) {
+ public boolean connectPanDevice(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- return mBluetoothPanProfileHandler.connectPanDevice(device);
+ synchronized (mBluetoothPanProfileHandler) {
+ return mBluetoothPanProfileHandler.connectPanDevice(device);
+ }
}
- public synchronized List<BluetoothDevice> getConnectedPanDevices() {
+ public List<BluetoothDevice> getConnectedPanDevices() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothPanProfileHandler.getConnectedPanDevices();
+ synchronized (mBluetoothPanProfileHandler) {
+ return mBluetoothPanProfileHandler.getConnectedPanDevices();
+ }
}
- public synchronized List<BluetoothDevice> getPanDevicesMatchingConnectionStates(
+ public List<BluetoothDevice> getPanDevicesMatchingConnectionStates(
int[] states) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states);
+ synchronized (mBluetoothPanProfileHandler) {
+ return mBluetoothPanProfileHandler.getPanDevicesMatchingConnectionStates(states);
+ }
}
- public synchronized boolean disconnectPanDevice(BluetoothDevice device) {
+ public boolean disconnectPanDevice(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- return mBluetoothPanProfileHandler.disconnectPanDevice(device);
+ synchronized (mBluetoothPanProfileHandler) {
+ return mBluetoothPanProfileHandler.disconnectPanDevice(device);
+ }
}
- /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+ /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
String iface,
int state,
int role) {
- mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role);
+ synchronized (mBluetoothPanProfileHandler) {
+ mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, iface, state, role);
+ }
}
- /*package*/ synchronized void handlePanDeviceStateChange(BluetoothDevice device,
+ /*package*/void handlePanDeviceStateChange(BluetoothDevice device,
int state, int role) {
- mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role);
+ synchronized (mBluetoothPanProfileHandler) {
+ mBluetoothPanProfileHandler.handlePanDeviceStateChange(device, null, state, role);
+ }
}
/**** Handlers for Input Device Profile ****/
+ // This needs to be converted to state machine
- public synchronized boolean connectInputDevice(BluetoothDevice device) {
+ public boolean connectInputDevice(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
- return mBluetoothInputProfileHandler.connectInputDevice(device, state);
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.connectInputDevice(device, state);
+ }
}
- public synchronized boolean connectInputDeviceInternal(BluetoothDevice device) {
- return mBluetoothInputProfileHandler.connectInputDeviceInternal(device);
+ public boolean connectInputDeviceInternal(BluetoothDevice device) {
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.connectInputDeviceInternal(device);
+ }
}
- public synchronized boolean disconnectInputDevice(BluetoothDevice device) {
+ public boolean disconnectInputDevice(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
BluetoothDeviceProfileState state = mDeviceProfileState.get(device.getAddress());
- return mBluetoothInputProfileHandler.disconnectInputDevice(device, state);
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.disconnectInputDevice(device, state);
+ }
}
- public synchronized boolean disconnectInputDeviceInternal(BluetoothDevice device) {
- return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
+ public boolean disconnectInputDeviceInternal(BluetoothDevice device) {
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.disconnectInputDeviceInternal(device);
+ }
}
- public synchronized int getInputDeviceConnectionState(BluetoothDevice device) {
+ public int getInputDeviceConnectionState(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device);
-
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.getInputDeviceConnectionState(device);
+ }
}
- public synchronized List<BluetoothDevice> getConnectedInputDevices() {
+ public List<BluetoothDevice> getConnectedInputDevices() {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothInputProfileHandler.getConnectedInputDevices();
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.getConnectedInputDevices();
+ }
}
- public synchronized List<BluetoothDevice> getInputDevicesMatchingConnectionStates(
+ public List<BluetoothDevice> getInputDevicesMatchingConnectionStates(
int[] states) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states);
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.getInputDevicesMatchingConnectionStates(states);
+ }
}
- public synchronized int getInputDevicePriority(BluetoothDevice device) {
+ public int getInputDevicePriority(BluetoothDevice device) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
- return mBluetoothInputProfileHandler.getInputDevicePriority(device);
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.getInputDevicePriority(device);
+ }
}
- public synchronized boolean setInputDevicePriority(BluetoothDevice device, int priority) {
+ public boolean setInputDevicePriority(BluetoothDevice device, int priority) {
mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
"Need BLUETOOTH_ADMIN permission");
- return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority);
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.setInputDevicePriority(device, priority);
+ }
}
- /*package*/synchronized List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
- return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states);
+ /*package*/List<BluetoothDevice> lookupInputDevicesMatchingStates(int[] states) {
+ synchronized (mBluetoothInputProfileHandler) {
+ return mBluetoothInputProfileHandler.lookupInputDevicesMatchingStates(states);
+ }
}
- /*package*/ synchronized void handleInputDevicePropertyChange(String address, boolean connected) {
- mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected);
+ /*package*/void handleInputDevicePropertyChange(String address, boolean connected) {
+ synchronized (mBluetoothInputProfileHandler) {
+ mBluetoothInputProfileHandler.handleInputDevicePropertyChange(address, connected);
+ }
}
public boolean connectHeadset(String address) {
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 81346b4..332a0fa 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -16,6 +16,10 @@
package android.view;
+import android.graphics.Canvas;
+import android.os.Handler;
+import android.os.Message;
+import android.widget.FrameLayout;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -83,6 +87,7 @@ public abstract class LayoutInflater {
private static final String TAG_MERGE = "merge";
private static final String TAG_INCLUDE = "include";
+ private static final String TAG_1995 = "blink";
private static final String TAG_REQUEST_FOCUS = "requestFocus";
/**
@@ -454,7 +459,12 @@ public abstract class LayoutInflater {
rInflate(parser, root, attrs, false);
} else {
// Temp is the root view that was found in the xml
- View temp = createViewFromTag(root, name, attrs);
+ View temp;
+ if (TAG_1995.equals(name)) {
+ temp = new BlinkLayout(mContext, attrs);
+ } else {
+ temp = createViewFromTag(root, name, attrs);
+ }
ViewGroup.LayoutParams params = null;
@@ -605,10 +615,9 @@ public abstract class LayoutInflater {
* Throw an exception because the specified class is not allowed to be inflated.
*/
private void failNotAllowed(String name, String prefix, AttributeSet attrs) {
- InflateException ie = new InflateException(attrs.getPositionDescription()
+ throw new InflateException(attrs.getPositionDescription()
+ ": Class not allowed to be inflated "
+ (prefix != null ? (prefix + name) : name));
- throw ie;
}
/**
@@ -720,6 +729,12 @@ public abstract class LayoutInflater {
parseInclude(parser, parent, attrs);
} else if (TAG_MERGE.equals(name)) {
throw new InflateException("<merge /> must be the root element");
+ } else if (TAG_1995.equals(name)) {
+ final View view = new BlinkLayout(mContext, attrs);
+ final ViewGroup viewGroup = (ViewGroup) parent;
+ final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
+ rInflate(parser, view, attrs, true);
+ viewGroup.addView(view, params);
} else {
final View view = createViewFromTag(parent, name, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
@@ -847,5 +862,64 @@ public abstract class LayoutInflater {
parser.getDepth() > currentDepth) && type != XmlPullParser.END_DOCUMENT) {
// Empty
}
- }
+ }
+
+ private static class BlinkLayout extends FrameLayout {
+ private static final int MESSAGE_BLINK = 0x42;
+ private static final int BLINK_DELAY = 500;
+
+ private boolean mBlink;
+ private boolean mBlinkState;
+ private final Handler mHandler;
+
+ public BlinkLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mHandler = new Handler(new Handler.Callback() {
+ @Override
+ public boolean handleMessage(Message msg) {
+ if (msg.what == MESSAGE_BLINK) {
+ if (mBlink) {
+ mBlinkState = !mBlinkState;
+ makeBlink();
+ }
+ invalidate();
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+ private void makeBlink() {
+ Message message = mHandler.obtainMessage(MESSAGE_BLINK);
+ mHandler.sendMessageDelayed(message, BLINK_DELAY);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ mBlink = true;
+ mBlinkState = true;
+
+ makeBlink();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ mBlink = false;
+ mBlinkState = true;
+
+ mHandler.removeMessages(MESSAGE_BLINK);
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ if (mBlinkState) {
+ super.dispatchDraw(canvas);
+ }
+ }
+ }
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ecb6bbb..d5f573c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -49,8 +49,6 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.os.RemoteException;
import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.text.format.DateUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pool;
@@ -1709,6 +1707,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*/
static final int DRAG_HOVERED = 0x00000002;
+ /**
+ * Indicates whether the view is drawn in right-to-left direction.
+ *
+ * @hide
+ */
+ static final int RESOLVED_LAYOUT_RTL = 0x00000004;
+
/* End of masks for mPrivateFlags2 */
static final int DRAG_MASK = DRAG_CAN_ACCEPT | DRAG_HOVERED;
@@ -8488,6 +8493,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mPrivateFlags &= ~AWAKEN_SCROLL_BARS_ON_ATTACH;
}
jumpDrawablesToCurrentState();
+
+ // We are supposing here that the parent directionality will be resolved before its children
+ // View horizontalDirection public attribute resolution to an internal var.
+ // Resolving the layout direction. LTR is set initially.
+ mPrivateFlags2 &= ~RESOLVED_LAYOUT_RTL;
+ switch (getHorizontalDirection()) {
+ case HORIZONTAL_DIRECTION_INHERIT:
+ // If this is root view, no need to look at parent's layout dir.
+ if (mParent != null && mParent instanceof ViewGroup &&
+ ((ViewGroup) mParent).isLayoutRtl()) {
+ mPrivateFlags2 |= RESOLVED_LAYOUT_RTL;
+ }
+ break;
+ case HORIZONTAL_DIRECTION_RTL:
+ mPrivateFlags2 |= RESOLVED_LAYOUT_RTL;
+ break;
+ }
}
/**
@@ -8876,6 +8898,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
// Destroy any previous software drawing cache if needed
switch (mLayerType) {
+ case LAYER_TYPE_HARDWARE:
+ if (mHardwareLayer != null) {
+ mHardwareLayer.destroy();
+ mHardwareLayer = null;
+ }
+ // fall through - unaccelerated views may use software layer mechanism instead
case LAYER_TYPE_SOFTWARE:
if (mDrawingCache != null) {
mDrawingCache.recycle();
@@ -8887,12 +8915,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mUnscaledDrawingCache = null;
}
break;
- case LAYER_TYPE_HARDWARE:
- if (mHardwareLayer != null) {
- mHardwareLayer.destroy();
- mHardwareLayer = null;
- }
- break;
default:
break;
}
@@ -9975,6 +9997,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * <p>Indicates whether or not this view's layout is right-to-left. This is resolved from
+ * layout attribute and/or the inherited value from the parent.</p>
+ *
+ * @return true if the layout is right-to-left.
+ */
+ public boolean isLayoutRtl() {
+ return (mPrivateFlags2 & RESOLVED_LAYOUT_RTL) == RESOLVED_LAYOUT_RTL;
+ }
+
+ /**
* Assign a size and position to a view and all of its
* descendants
*
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 1534099..4aa8727 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -92,21 +92,6 @@ public class ViewDebug {
public static final boolean TRACE_RECYCLER = false;
/**
- * Enables or disables motion events tracing. Any invoker of
- * {@link #trace(View, MotionEvent, MotionEventTraceType)} should first check
- * that this value is set to true as not to affect performance.
- *
- * @hide
- */
- public static final boolean TRACE_MOTION_EVENTS = false;
-
- /**
- * The system property of dynamic switch for capturing view information
- * when it is set, we dump interested fields and methods for the view on focus
- */
- static final String SYSTEM_PROPERTY_CAPTURE_VIEW = "debug.captureview";
-
- /**
* The system property of dynamic switch for capturing event information
* when it is set, we log key events, touch/motion and trackball events
*/
@@ -170,12 +155,6 @@ public class ViewDebug {
@Debug.DebugProperty
public static boolean consistencyCheckEnabled = false;
- static {
- if (false) {
- Debug.setFieldsOn(ViewDebug.class, true);
- }
- }
-
/**
* This annotation can be used to mark fields and methods to be dumped by
* the view server. Only non-void methods with no arguments can be annotated
@@ -424,21 +403,6 @@ public class ViewDebug {
private static String sRecyclerTracePrefix;
/**
- * Defines the type of motion events trace to output to the motion events traces file.
- *
- * @hide
- */
- public enum MotionEventTraceType {
- DISPATCH,
- ON_INTERCEPT,
- ON_TOUCH
- }
-
- private static BufferedWriter sMotionEventTraces;
- private static ViewAncestor sMotionEventRoot;
- private static String sMotionEventTracePrefix;
-
- /**
* Returns the number of instanciated Views.
*
* @return The number of Views instanciated in the current process.
@@ -574,6 +538,7 @@ public class ViewDebug {
recyclerDump = new File(recyclerDump, sRecyclerTracePrefix + ".traces");
try {
if (recyclerDump.exists()) {
+ //noinspection ResultOfMethodCallIgnored
recyclerDump.delete();
}
final FileOutputStream file = new FileOutputStream(recyclerDump);
@@ -732,146 +697,6 @@ public class ViewDebug {
sHierarhcyRoot = null;
}
- /**
- * Outputs a trace to the currently opened traces file. The trace contains the class name
- * and instance's hashcode of the specified view as well as the supplied trace type.
- *
- * @param view the view to trace
- * @param event the event of the trace
- * @param type the type of the trace
- *
- * @hide
- */
- public static void trace(View view, MotionEvent event, MotionEventTraceType type) {
- if (sMotionEventTraces == null) {
- return;
- }
-
- try {
- sMotionEventTraces.write(type.name());
- sMotionEventTraces.write(' ');
- sMotionEventTraces.write(event.getAction());
- sMotionEventTraces.write(' ');
- sMotionEventTraces.write(view.getClass().getName());
- sMotionEventTraces.write('@');
- sMotionEventTraces.write(Integer.toHexString(view.hashCode()));
- sHierarchyTraces.newLine();
- } catch (IOException e) {
- Log.w("View", "Error while dumping trace of event " + event + " for view " + view);
- }
- }
-
- /**
- * Starts tracing the motion events for the hierarchy of the specificy view.
- * The trace is identified by a prefix, used to build the traces files names:
- * <code>/EXTERNAL/motion-events/PREFIX.traces</code> and
- * <code>/EXTERNAL/motion-events/PREFIX.tree</code>.
- *
- * Only one view hierarchy can be traced at the same time. After calling this method, any
- * other invocation will result in a <code>IllegalStateException</code> unless
- * {@link #stopMotionEventTracing()} is invoked before.
- *
- * Calling this method creates the file <code>/EXTERNAL/motion-events/PREFIX.traces</code>
- * containing all the traces (or method calls) relative to the specified view's hierarchy.
- *
- * This method will return immediately if TRACE_HIERARCHY is false.
- *
- * @param prefix the traces files name prefix
- * @param view the view whose hierarchy must be traced
- *
- * @see #stopMotionEventTracing()
- * @see #trace(View, MotionEvent, android.view.ViewDebug.MotionEventTraceType)
- *
- * @hide
- */
- public static void startMotionEventTracing(String prefix, View view) {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (!TRACE_MOTION_EVENTS) {
- return;
- }
-
- if (sMotionEventRoot != null) {
- throw new IllegalStateException("You must call stopMotionEventTracing() before running" +
- " a new trace!");
- }
-
- File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "motion-events/");
- //noinspection ResultOfMethodCallIgnored
- hierarchyDump.mkdirs();
-
- hierarchyDump = new File(hierarchyDump, prefix + ".traces");
- sMotionEventTracePrefix = prefix;
-
- try {
- sMotionEventTraces = new BufferedWriter(new FileWriter(hierarchyDump), 32 * 1024);
- } catch (IOException e) {
- Log.e("View", "Could not dump view hierarchy");
- return;
- }
-
- sMotionEventRoot = (ViewAncestor) view.getRootView().getParent();
- }
-
- /**
- * Stops the current motion events tracing. This method closes the file
- * <code>/EXTERNAL/motion-events/PREFIX.traces</code>.
- *
- * Calling this method creates the file <code>/EXTERNAL/motion-events/PREFIX.tree</code>
- * containing the view hierarchy of the view supplied to
- * {@link #startMotionEventTracing(String, View)}.
- *
- * This method will return immediately if TRACE_HIERARCHY is false.
- *
- * @see #startMotionEventTracing(String, View)
- * @see #trace(View, MotionEvent, android.view.ViewDebug.MotionEventTraceType)
- *
- * @hide
- */
- public static void stopMotionEventTracing() {
- //noinspection PointlessBooleanExpression,ConstantConditions
- if (!TRACE_MOTION_EVENTS) {
- return;
- }
-
- if (sMotionEventRoot == null || sMotionEventTraces == null) {
- throw new IllegalStateException("You must call startMotionEventTracing() before" +
- " stopMotionEventTracing()!");
- }
-
- try {
- sMotionEventTraces.close();
- } catch (IOException e) {
- Log.e("View", "Could not write view traces");
- }
- sMotionEventTraces = null;
-
- File hierarchyDump = new File(Environment.getExternalStorageDirectory(), "motion-events/");
- //noinspection ResultOfMethodCallIgnored
- hierarchyDump.mkdirs();
- hierarchyDump = new File(hierarchyDump, sMotionEventTracePrefix + ".tree");
-
- BufferedWriter out;
- try {
- out = new BufferedWriter(new FileWriter(hierarchyDump), 8 * 1024);
- } catch (IOException e) {
- Log.e("View", "Could not dump view hierarchy");
- return;
- }
-
- View view = sMotionEventRoot.getView();
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
- dumpViewHierarchy(group, out, 0);
- try {
- out.close();
- } catch (IOException e) {
- Log.e("View", "Could not dump view hierarchy");
- }
- }
-
- sHierarhcyRoot = null;
- }
-
static void dispatchCommand(View view, String command, String parameters,
OutputStream clientStream) throws IOException {
@@ -1069,8 +894,10 @@ public class ViewDebug {
try {
T[] data = operation.pre();
long start = Debug.threadCpuTimeNanos();
+ //noinspection unchecked
operation.run(data);
duration[0] = Debug.threadCpuTimeNanos() - start;
+ //noinspection unchecked
operation.post(data);
} finally {
latch.countDown();
@@ -1201,12 +1028,7 @@ public class ViewDebug {
cache[0] = captureView.createSnapshot(
Bitmap.Config.ARGB_8888, 0, skpiChildren);
} catch (OutOfMemoryError e) {
- try {
- cache[0] = captureView.createSnapshot(
- Bitmap.Config.ARGB_4444, 0, skpiChildren);
- } catch (OutOfMemoryError e2) {
- Log.w("View", "Out of memory for bitmap");
- }
+ Log.w("View", "Out of memory for bitmap");
} finally {
latch.countDown();
}
@@ -1316,7 +1138,6 @@ public class ViewDebug {
}
final HashMap<Class<?>, Field[]> map = sFieldsForClasses;
- final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations;
Field[] fields = map.get(klass);
if (fields != null) {
@@ -1332,7 +1153,7 @@ public class ViewDebug {
if (field.isAnnotationPresent(ExportedProperty.class)) {
field.setAccessible(true);
foundFields.add(field);
- annotations.put(field, field.getAnnotation(ExportedProperty.class));
+ sAnnotations.put(field, field.getAnnotation(ExportedProperty.class));
}
}
@@ -1351,7 +1172,6 @@ public class ViewDebug {
}
final HashMap<Class<?>, Method[]> map = sMethodsForClasses;
- final HashMap<AccessibleObject, ExportedProperty> annotations = sAnnotations;
Method[] methods = map.get(klass);
if (methods != null) {
@@ -1369,7 +1189,7 @@ public class ViewDebug {
method.getReturnType() != Void.class) {
method.setAccessible(true);
foundMethods.add(method);
- annotations.put(method, method.getAnnotation(ExportedProperty.class));
+ sAnnotations.put(method, method.getAnnotation(ExportedProperty.class));
}
}
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 5a418f3..4e52e40 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -466,16 +466,34 @@ public interface WindowManagerPolicy {
public int getMaxWallpaperLayer();
/**
- * Return the display width available after excluding the window
- * decor.
+ * Return the display width available after excluding any screen
+ * decorations that can never be removed. That is, system bar or
+ * button bar.
*/
- public int getNonDecorDisplayWidth(int fullWidth);
+ public int getNonDecorDisplayWidth(int rotation, int fullWidth);
/**
- * Return the display height available after excluding the screen
- * decor.
+ * Return the display height available after excluding any screen
+ * decorations that can never be removed. That is, system bar or
+ * button bar.
*/
- public int getNonDecorDisplayHeight(int fullHeight);
+ public int getNonDecorDisplayHeight(int rotation, int fullHeight);
+
+ /**
+ * Return the available screen width that we should report for the
+ * configuration. This must be no larger than
+ * {@link #getNonDecorDisplayWidth(int, int)}; it may be smaller than
+ * that to account for more transient decoration like a status bar.
+ */
+ public int getConfigDisplayWidth(int rotation, int fullWidth);
+
+ /**
+ * Return the available screen height that we should report for the
+ * configuration. This must be no larger than
+ * {@link #getNonDecorDisplayHeight(int, int)}; it may be smaller than
+ * that to account for more transient decoration like a status bar.
+ */
+ public int getConfigDisplayHeight(int rotation, int fullHeight);
/**
* Return whether the given window should forcibly hide everything
diff --git a/core/java/android/view/accessibility/AccessibilityRecord.java b/core/java/android/view/accessibility/AccessibilityRecord.java
index fecf9df..7819b17 100644
--- a/core/java/android/view/accessibility/AccessibilityRecord.java
+++ b/core/java/android/view/accessibility/AccessibilityRecord.java
@@ -341,7 +341,7 @@ public class AccessibilityRecord {
*
* @return An instance.
*/
- protected static AccessibilityRecord obtain() {
+ public static AccessibilityRecord obtain() {
synchronized (sPoolLock) {
if (sPool != null) {
AccessibilityRecord record = sPool;
diff --git a/core/java/android/widget/ExpandableListView.java b/core/java/android/widget/ExpandableListView.java
index f862368..ead9b4f 100644
--- a/core/java/android/widget/ExpandableListView.java
+++ b/core/java/android/widget/ExpandableListView.java
@@ -599,12 +599,35 @@ public class ExpandableListView extends ListView {
* was already expanded, this will return false)
*/
public boolean expandGroup(int groupPos) {
- boolean retValue = mConnector.expandGroup(groupPos);
+ return expandGroup(groupPos, false);
+ }
+
+ /**
+ * Expand a group in the grouped list view
+ *
+ * @param groupPos the group to be expanded
+ * @param animate true if the expanding group should be animated in
+ * @return True if the group was expanded, false otherwise (if the group
+ * was already expanded, this will return false)
+ */
+ public boolean expandGroup(int groupPos, boolean animate) {
+ PositionMetadata pm = mConnector.getFlattenedPos(ExpandableListPosition.obtain(
+ ExpandableListPosition.GROUP, groupPos, -1, -1));
+ boolean retValue = mConnector.expandGroup(pm);
if (mOnGroupExpandListener != null) {
mOnGroupExpandListener.onGroupExpand(groupPos);
}
-
+
+ if (animate) {
+ final int groupFlatPos = pm.position.flatListPos;
+
+ final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount();
+ smoothScrollToPosition(shiftedGroupPosition + mAdapter.getChildrenCount(groupPos),
+ shiftedGroupPosition);
+ }
+ pm.recycle();
+
return retValue;
}
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 86fefaf..bac849e 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1331,7 +1331,7 @@ public class LinearLayout extends ViewGroup {
void layoutVertical() {
final int paddingLeft = mPaddingLeft;
- int childTop = mPaddingTop;
+ int childTop;
int childLeft;
// Where right end of child should go
@@ -1346,19 +1346,21 @@ public class LinearLayout extends ViewGroup {
final int majorGravity = mGravity & Gravity.VERTICAL_GRAVITY_MASK;
final int minorGravity = mGravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- if (majorGravity != Gravity.TOP) {
- switch (majorGravity) {
- case Gravity.BOTTOM:
- // mTotalLength contains the padding already, we add the top
- // padding to compensate
- childTop = mBottom - mTop + mPaddingTop - mTotalLength;
- break;
-
- case Gravity.CENTER_VERTICAL:
- childTop += ((mBottom - mTop) - mTotalLength) / 2;
- break;
- }
-
+ switch (majorGravity) {
+ case Gravity.BOTTOM:
+ // mTotalLength contains the padding already
+ childTop = mPaddingTop + mBottom - mTop - mTotalLength;
+ break;
+
+ // mTotalLength contains the padding already
+ case Gravity.CENTER_VERTICAL:
+ childTop = mPaddingTop + (mBottom - mTop - mTotalLength) / 2;
+ break;
+
+ case Gravity.TOP:
+ default:
+ childTop = mPaddingTop;
+ break;
}
for (int i = 0; i < count; i++) {
@@ -1376,12 +1378,8 @@ public class LinearLayout extends ViewGroup {
if (gravity < 0) {
gravity = minorGravity;
}
-
- switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
- case Gravity.LEFT:
- childLeft = paddingLeft + lp.leftMargin;
- break;
+ switch (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
case Gravity.CENTER_HORIZONTAL:
childLeft = paddingLeft + ((childSpace - childWidth) / 2)
+ lp.leftMargin - lp.rightMargin;
@@ -1390,11 +1388,13 @@ public class LinearLayout extends ViewGroup {
case Gravity.RIGHT:
childLeft = childRight - childWidth - lp.rightMargin;
break;
+
+ case Gravity.LEFT:
default:
- childLeft = paddingLeft;
+ childLeft = paddingLeft + lp.leftMargin;
break;
}
-
+
if (hasDividerBeforeChildAt(i)) {
childTop += mDividerHeight;
}
@@ -1418,10 +1418,11 @@ public class LinearLayout extends ViewGroup {
* @see #onLayout(boolean, int, int, int, int)
*/
void layoutHorizontal() {
+ final boolean isLayoutRtl = isLayoutRtl();
final int paddingTop = mPaddingTop;
int childTop;
- int childLeft = mPaddingLeft;
+ int childLeft;
// Where bottom of child should go
final int height = mBottom - mTop;
@@ -1440,25 +1441,37 @@ public class LinearLayout extends ViewGroup {
final int[] maxAscent = mMaxAscent;
final int[] maxDescent = mMaxDescent;
- if (majorGravity != Gravity.LEFT) {
- switch (majorGravity) {
- case Gravity.RIGHT:
- // mTotalLength contains the padding already, we add the left
- // padding to compensate
- childLeft = mRight - mLeft + mPaddingLeft - mTotalLength;
- break;
-
- case Gravity.CENTER_HORIZONTAL:
- childLeft += ((mRight - mLeft) - mTotalLength) / 2;
- break;
- }
+ switch (majorGravity) {
+ case Gravity.RIGHT:
+ // mTotalLength contains the padding already
+ childLeft = mPaddingLeft + mRight - mLeft - mTotalLength;
+ break;
+
+ case Gravity.CENTER_HORIZONTAL:
+ // mTotalLength contains the padding already
+ childLeft = mPaddingLeft + (mRight - mLeft - mTotalLength) / 2;
+ break;
+
+ case Gravity.LEFT:
+ default:
+ childLeft = mPaddingLeft;
+ break;
+ }
+
+ int start = 0;
+ int dir = 1;
+ //In case of RTL, start drawing from the last child.
+ if (isLayoutRtl) {
+ start = count - 1;
+ dir = -1;
}
for (int i = 0; i < count; i++) {
- final View child = getVirtualChildAt(i);
+ int childIndex = start + dir * i;
+ final View child = getVirtualChildAt(childIndex);
if (child == null) {
- childLeft += measureNullChild(i);
+ childLeft += measureNullChild(childIndex);
} else if (child.getVisibility() != GONE) {
final int childWidth = child.getMeasuredWidth();
final int childHeight = child.getMeasuredHeight();
@@ -1512,7 +1525,7 @@ public class LinearLayout extends ViewGroup {
break;
}
- if (hasDividerBeforeChildAt(i)) {
+ if (hasDividerBeforeChildAt(childIndex)) {
childLeft += mDividerWidth;
}
@@ -1522,7 +1535,7 @@ public class LinearLayout extends ViewGroup {
childLeft += childWidth + lp.rightMargin +
getNextLocationOffset(child);
- i += getChildrenSkipCount(child, i);
+ i += getChildrenSkipCount(child, childIndex);
}
}
}