summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/annotation/PrivateApi.java31
-rw-r--r--core/java/android/app/ActivityThread.java42
-rw-r--r--core/java/android/app/AppOpsManager.java4
-rw-r--r--core/java/android/app/ContextImpl.java206
-rw-r--r--core/java/android/app/LoadedApk.java51
-rw-r--r--core/java/android/app/Notification.java2
-rw-r--r--core/java/android/app/PendingIntent.java40
-rw-r--r--core/java/android/app/WallpaperManager.java66
-rw-r--r--core/java/android/app/backup/IBackupManager.aidl4
-rw-r--r--core/java/android/bluetooth/BluetoothAdapter.java285
-rw-r--r--core/java/android/bluetooth/BluetoothAdvScanData.java152
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java72
-rw-r--r--core/java/android/bluetooth/BluetoothGattServer.java2
-rw-r--r--core/java/android/bluetooth/BluetoothGattService.java23
-rw-r--r--core/java/android/bluetooth/BluetoothUuid.java16
-rw-r--r--core/java/android/bluetooth/IBluetoothGatt.aidl15
-rw-r--r--core/java/android/bluetooth/IBluetoothGattCallback.aidl2
-rw-r--r--core/java/android/bluetooth/package.html16
-rw-r--r--core/java/android/content/ClipDescription.java2
-rw-r--r--core/java/android/content/ContentProvider.java6
-rw-r--r--core/java/android/content/ContentResolver.java12
-rw-r--r--core/java/android/content/Intent.java10
-rw-r--r--core/java/android/hardware/Camera.java30
-rw-r--r--core/java/android/hardware/SensorManager.java4
-rw-r--r--core/java/android/hardware/display/DisplayManager.java21
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java33
-rw-r--r--core/java/android/hardware/display/IDisplayManager.aidl23
-rw-r--r--core/java/android/net/ConnectivityManager.java7
-rw-r--r--core/java/android/net/IConnectivityManager.aidl4
-rw-r--r--core/java/android/net/MobileDataStateTracker.java11
-rw-r--r--core/java/android/net/VpnService.java7
-rw-r--r--core/java/android/os/AsyncTask.java2
-rw-r--r--core/java/android/os/Build.java2
-rw-r--r--core/java/android/os/INetworkManagementService.aidl2
-rw-r--r--core/java/android/os/Vibrator.java4
-rw-r--r--core/java/android/preference/PreferenceActivity.java7
-rw-r--r--core/java/android/print/PrinterCapabilitiesInfo.java6
-rw-r--r--core/java/android/provider/ContactsContract.java15
-rw-r--r--core/java/android/provider/DocumentsContract.java2
-rw-r--r--core/java/android/provider/Settings.java6
-rw-r--r--core/java/android/text/format/Time.java2
-rw-r--r--core/java/android/util/LongSparseArray.java2
-rw-r--r--core/java/android/util/LongSparseLongArray.java2
-rw-r--r--core/java/android/util/SparseArray.java2
-rw-r--r--core/java/android/util/SparseBooleanArray.java2
-rw-r--r--core/java/android/util/SparseIntArray.java2
-rw-r--r--core/java/android/util/SparseLongArray.java2
-rw-r--r--core/java/android/view/View.java2
-rw-r--r--core/java/android/view/ViewConfiguration.java39
-rw-r--r--core/java/android/view/ViewRootImpl.java72
-rw-r--r--core/java/android/view/VolumePanel.java1
-rw-r--r--core/java/android/view/WindowManager.java7
-rw-r--r--core/java/android/webkit/WebView.java9
-rw-r--r--core/java/android/webkit/WebViewFactoryProvider.java5
-rw-r--r--core/java/android/widget/AbsListView.java182
-rw-r--r--core/java/android/widget/CalendarView.java53
-rw-r--r--core/java/android/widget/FastScroller.java30
-rw-r--r--core/java/android/widget/ImageView.java2
-rw-r--r--core/java/android/widget/PopupWindow.java2
-rw-r--r--core/java/android/widget/ProgressBar.java5
-rw-r--r--core/java/android/widget/ShareActionProvider.java2
-rw-r--r--core/java/android/widget/SpellChecker.java6
-rw-r--r--core/java/android/widget/TextView.java4
-rw-r--r--core/java/com/android/internal/app/ProcessStats.java6
-rw-r--r--core/java/com/android/internal/content/PackageMonitor.java10
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java6
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl2
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java36
-rw-r--r--core/java/com/android/internal/view/menu/ListMenuPresenter.java2
-rw-r--r--core/java/com/android/internal/view/menu/MenuBuilder.java14
70 files changed, 1103 insertions, 653 deletions
diff --git a/core/java/android/annotation/PrivateApi.java b/core/java/android/annotation/PrivateApi.java
new file mode 100644
index 0000000..985eafe
--- /dev/null
+++ b/core/java/android/annotation/PrivateApi.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Indicates an API is exposed for use by bundled applications.
+ * <p>
+ * These APIs are not guaranteed to remain consistent release-to-release,
+ * and are not for use by apps linking against the SDK.
+ * @hide
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface PrivateApi {
+}
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index b103e71..9a3478e 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -157,7 +157,7 @@ public final class ActivityThread {
private static final int LOG_ON_PAUSE_CALLED = 30021;
private static final int LOG_ON_RESUME_CALLED = 30022;
- static ContextImpl mSystemContext = null;
+ private ContextImpl mSystemContext;
static IPackageManager sPackageManager;
@@ -1700,7 +1700,7 @@ public final class ActivityThread {
? mBoundApplication.processName : null)
+ ")");
packageInfo =
- new LoadedApk(this, aInfo, compatInfo, this, baseLoader,
+ new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
if (includeCode) {
@@ -1753,26 +1753,15 @@ public final class ActivityThread {
public ContextImpl getSystemContext() {
synchronized (this) {
if (mSystemContext == null) {
- ContextImpl context =
- ContextImpl.createSystemContext(this);
- LoadedApk info = new LoadedApk(this, "android", context, null,
- CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO);
- context.init(info, null, this);
- context.getResources().updateConfiguration(mResourcesManager.getConfiguration(),
- mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
- mSystemContext = context;
- //Slog.i(TAG, "Created system resources " + context.getResources()
- // + ": " + context.getResources().getConfiguration());
+ mSystemContext = ContextImpl.createSystemContext(this);
}
+ return mSystemContext;
}
- return mSystemContext;
}
public void installSystemApplicationInfo(ApplicationInfo info) {
synchronized (this) {
- ContextImpl context = getSystemContext();
- context.init(new LoadedApk(this, "android", context, info,
- CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO), null, this);
+ getSystemContext().installSystemApplicationInfo(info);
// give ourselves a default profiler
mProfiler = new Profiler();
@@ -2258,8 +2247,7 @@ public final class ActivityThread {
private Context createBaseContextForActivity(ActivityClientRecord r,
final Activity activity) {
- ContextImpl appContext = new ContextImpl();
- appContext.init(r.packageInfo, r.token, this);
+ ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, r.token);
appContext.setOuterContext(activity);
// For debugging purposes, if the activity's package name contains the value of
@@ -2544,8 +2532,7 @@ public final class ActivityThread {
agent = (BackupAgent) cl.loadClass(classname).newInstance();
// set up the agent's context
- ContextImpl context = new ContextImpl();
- context.init(packageInfo, null, this);
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(agent);
agent.attach(context);
@@ -2617,11 +2604,10 @@ public final class ActivityThread {
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
- ContextImpl context = new ContextImpl();
- context.init(packageInfo, null, this);
+ ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
+ context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
- context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
@@ -4217,8 +4203,7 @@ public final class ActivityThread {
}
updateDefaultDensity();
- final ContextImpl appContext = new ContextImpl();
- appContext.init(data.info, null, this);
+ final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if (!Process.isIsolated()) {
final File cacheDir = appContext.getCacheDir();
@@ -4334,8 +4319,7 @@ public final class ActivityThread {
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true);
- ContextImpl instrContext = new ContextImpl();
- instrContext.init(pi, null, this);
+ ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
java.lang.ClassLoader cl = instrContext.getClassLoader();
@@ -4950,8 +4934,8 @@ public final class ActivityThread {
UserHandle.myUserId());
try {
mInstrumentation = new Instrumentation();
- ContextImpl context = new ContextImpl();
- context.init(getSystemContext().mPackageInfo, null, this);
+ ContextImpl context = ContextImpl.createAppContext(
+ this, getSystemContext().mPackageInfo);
Application app = Instrumentation.newApplication(Application.class, context);
mAllApplications.add(app);
mInitialApplication = app;
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index aece462..079cf7a 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -36,7 +36,7 @@ import android.os.RemoteException;
* API for interacting with "application operation" tracking.
*
* <p>This API is not generally intended for third party application developers; most
- * features are only available to system applicatins. Obtain an instance of it through
+ * features are only available to system applications. Obtain an instance of it through
* {@link Context#getSystemService(String) Context.getSystemService} with
* {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
*/
@@ -878,7 +878,7 @@ public class AppOpsManager {
}
/**
- * Like {@link #checkOp but instead of throwing a {@link SecurityException} it
+ * Like {@link #checkOp} but instead of throwing a {@link SecurityException} it
* returns {@link #MODE_ERRORED}.
*/
public int checkOpNoThrow(String op, int uid, String packageName) {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 8d127c6..df50989 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -183,22 +183,31 @@ class ContextImpl extends Context {
*/
private static ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>> sSharedPrefs;
- /*package*/ LoadedApk mPackageInfo;
- private String mBasePackageName;
- private String mOpPackageName;
- private Resources mResources;
- /*package*/ ActivityThread mMainThread;
+ final ActivityThread mMainThread;
+ final LoadedApk mPackageInfo;
+
+ private final IBinder mActivityToken;
+
+ private final UserHandle mUser;
+
+ private final ApplicationContentResolver mContentResolver;
+
+ private final String mBasePackageName;
+ private final String mOpPackageName;
+
+ private final ResourcesManager mResourcesManager;
+ private final Resources mResources;
+ private final Display mDisplay; // may be null if default display
+ private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
+ private final Configuration mOverrideConfiguration;
+
+ private final boolean mRestricted;
+
private Context mOuterContext;
- private IBinder mActivityToken = null;
- private ApplicationContentResolver mContentResolver;
private int mThemeResource = 0;
private Resources.Theme mTheme = null;
private PackageManager mPackageManager;
- private Display mDisplay; // may be null if default display
private Context mReceiverRestrictedContext = null;
- private boolean mRestricted;
- private UserHandle mUser;
- private ResourcesManager mResourcesManager;
private final Object mSync = new Object();
@@ -220,8 +229,6 @@ class ContextImpl extends Context {
private static final String[] EMPTY_FILE_LIST = {};
- final private DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
-
/**
* Override this class when the system service constructor needs a
* ContextImpl. Else, use StaticServiceFetcher below.
@@ -356,10 +363,11 @@ class ContextImpl extends Context {
ctx.mMainThread.getHandler());
}});
- registerService(CONNECTIVITY_SERVICE, new StaticServiceFetcher() {
- public Object createStaticService() {
+ registerService(CONNECTIVITY_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(CONNECTIVITY_SERVICE);
- return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b));
+ return new ConnectivityManager(IConnectivityManager.Stub.asInterface(b),
+ ctx.getPackageName());
}});
registerService(COUNTRY_DETECTOR, new StaticServiceFetcher() {
@@ -1878,20 +1886,17 @@ class ContextImpl extends Context {
@Override
public Context createPackageContextAsUser(String packageName, int flags, UserHandle user)
throws NameNotFoundException {
+ final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
if (packageName.equals("system") || packageName.equals("android")) {
- final ContextImpl context = new ContextImpl(mMainThread.getSystemContext());
- context.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
- context.init(mPackageInfo, null, mMainThread, mResources, mBasePackageName, user);
- return context;
+ return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
+ user, restricted, mDisplay, mOverrideConfiguration);
}
- LoadedApk pi =
- mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(), flags,
- user.getIdentifier());
+ LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
+ flags, user.getIdentifier());
if (pi != null) {
- ContextImpl c = new ContextImpl();
- c.mRestricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
- c.init(pi, null, mMainThread, mResources, mBasePackageName, user);
+ ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
+ user, restricted, mDisplay, mOverrideConfiguration);
if (c.mResources != null) {
return c;
}
@@ -1899,7 +1904,7 @@ class ContextImpl extends Context {
// Should be a better exception.
throw new PackageManager.NameNotFoundException(
- "Application package " + packageName + " not found");
+ "Application package " + packageName + " not found");
}
@Override
@@ -1908,12 +1913,8 @@ class ContextImpl extends Context {
throw new IllegalArgumentException("overrideConfiguration must not be null");
}
- ContextImpl c = new ContextImpl();
- c.init(mPackageInfo, null, mMainThread);
- c.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
- mPackageInfo.getOverlayDirs(), getDisplayId(), overrideConfiguration,
- mResources.getCompatibilityInfo(), mActivityToken);
- return c;
+ return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
+ mUser, mRestricted, mDisplay, overrideConfiguration);
}
@Override
@@ -1922,15 +1923,8 @@ class ContextImpl extends Context {
throw new IllegalArgumentException("display must not be null");
}
- int displayId = display.getDisplayId();
-
- ContextImpl context = new ContextImpl();
- context.init(mPackageInfo, null, mMainThread);
- context.mDisplay = display;
- DisplayAdjustments daj = getDisplayAdjustments(displayId);
- context.mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
- mPackageInfo.getOverlayDirs(), displayId, null, daj.getCompatibilityInfo(), null);
- return context;
+ return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
+ mUser, mRestricted, display, mOverrideConfiguration);
}
private int getDisplayId() {
@@ -1972,43 +1966,76 @@ class ContextImpl extends Context {
}
static ContextImpl createSystemContext(ActivityThread mainThread) {
- final ContextImpl context = new ContextImpl();
- context.init(Resources.getSystem(), mainThread, Process.myUserHandle());
+ LoadedApk packageInfo = new LoadedApk(mainThread);
+ ContextImpl context = new ContextImpl(null, mainThread,
+ packageInfo, null, null, false, null, null);
+ context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
+ context.mResourcesManager.getDisplayMetricsLocked(Display.DEFAULT_DISPLAY));
return context;
}
- ContextImpl() {
- mOuterContext = this;
+ static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
+ if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
+ return new ContextImpl(null, mainThread,
+ packageInfo, null, null, false, null, null);
}
- /**
- * Create a new ApplicationContext from an existing one. The new one
- * works and operates the same as the one it is copying.
- *
- * @param context Existing application context.
- */
- public ContextImpl(ContextImpl context) {
- mPackageInfo = context.mPackageInfo;
- mBasePackageName = context.mBasePackageName;
- mOpPackageName = context.mOpPackageName;
- mResources = context.mResources;
- mMainThread = context.mMainThread;
- mContentResolver = context.mContentResolver;
- mUser = context.mUser;
- mDisplay = context.mDisplay;
- mOuterContext = this;
- mDisplayAdjustments.setCompatibilityInfo(mPackageInfo.getCompatibilityInfo());
+ static ContextImpl createActivityContext(ActivityThread mainThread,
+ LoadedApk packageInfo, IBinder activityToken) {
+ if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
+ if (activityToken == null) throw new IllegalArgumentException("activityInfo");
+ return new ContextImpl(null, mainThread,
+ packageInfo, activityToken, null, false, null, null);
}
- final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread) {
- init(packageInfo, activityToken, mainThread, null, null, Process.myUserHandle());
- }
+ private ContextImpl(ContextImpl container, ActivityThread mainThread,
+ LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
+ Display display, Configuration overrideConfiguration) {
+ mOuterContext = this;
+
+ mMainThread = mainThread;
+ mActivityToken = activityToken;
+ mRestricted = restricted;
+
+ if (user == null) {
+ user = Process.myUserHandle();
+ }
+ mUser = user;
- final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread,
- Resources container, String basePackageName, UserHandle user) {
mPackageInfo = packageInfo;
- if (basePackageName != null) {
- mBasePackageName = mOpPackageName = basePackageName;
+ mContentResolver = new ApplicationContentResolver(this, mainThread, user);
+ mResourcesManager = ResourcesManager.getInstance();
+ mDisplay = display;
+ mOverrideConfiguration = overrideConfiguration;
+
+ final int displayId = getDisplayId();
+ CompatibilityInfo compatInfo = null;
+ if (container != null) {
+ compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();
+ }
+ if (compatInfo == null && displayId == Display.DEFAULT_DISPLAY) {
+ compatInfo = packageInfo.getCompatibilityInfo();
+ }
+ mDisplayAdjustments.setCompatibilityInfo(compatInfo);
+ mDisplayAdjustments.setActivityToken(activityToken);
+
+ Resources resources = packageInfo.getResources(mainThread);
+ if (resources != null) {
+ if (activityToken != null
+ || displayId != Display.DEFAULT_DISPLAY
+ || overrideConfiguration != null
+ || (compatInfo != null && compatInfo.applicationScale
+ != resources.getCompatibilityInfo().applicationScale)) {
+ resources = mResourcesManager.getTopLevelResources(
+ packageInfo.getResDir(), packageInfo.getOverlayDirs(), displayId,
+ overrideConfiguration, compatInfo, activityToken);
+ }
+ }
+ mResources = resources;
+
+ if (container != null) {
+ mBasePackageName = container.mBasePackageName;
+ mOpPackageName = container.mOpPackageName;
} else {
mBasePackageName = packageInfo.mPackageName;
ApplicationInfo ainfo = packageInfo.getApplicationInfo();
@@ -2022,45 +2049,10 @@ class ContextImpl extends Context {
mOpPackageName = mBasePackageName;
}
}
- mResources = mPackageInfo.getResources(mainThread);
- mResourcesManager = ResourcesManager.getInstance();
-
- CompatibilityInfo compatInfo =
- container == null ? null : container.getCompatibilityInfo();
- if (mResources != null &&
- ((compatInfo != null && compatInfo.applicationScale !=
- mResources.getCompatibilityInfo().applicationScale)
- || activityToken != null)) {
- if (DEBUG) {
- Log.d(TAG, "loaded context has different scaling. Using container's" +
- " compatiblity info:" + container.getDisplayMetrics());
- }
- if (compatInfo == null) {
- compatInfo = packageInfo.getCompatibilityInfo();
- }
- mDisplayAdjustments.setCompatibilityInfo(compatInfo);
- mDisplayAdjustments.setActivityToken(activityToken);
- mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
- mPackageInfo.getOverlayDirs(), Display.DEFAULT_DISPLAY, null, compatInfo,
- activityToken);
- } else {
- mDisplayAdjustments.setCompatibilityInfo(packageInfo.getCompatibilityInfo());
- mDisplayAdjustments.setActivityToken(activityToken);
- }
- mMainThread = mainThread;
- mActivityToken = activityToken;
- mContentResolver = new ApplicationContentResolver(this, mainThread, user);
- mUser = user;
}
- final void init(Resources resources, ActivityThread mainThread, UserHandle user) {
- mPackageInfo = null;
- mBasePackageName = null;
- mOpPackageName = null;
- mResources = resources;
- mMainThread = mainThread;
- mContentResolver = new ApplicationContentResolver(this, mainThread, user);
- mUser = user;
+ void installSystemApplicationInfo(ApplicationInfo info) {
+ mPackageInfo.installSystemApplicationInfo(info);
}
final void scheduleFinalCleanup(String who, String what) {
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 0115d1b..d409352 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -72,7 +72,7 @@ public final class LoadedApk {
private static final String TAG = "LoadedApk";
private final ActivityThread mActivityThread;
- private final ApplicationInfo mApplicationInfo;
+ private ApplicationInfo mApplicationInfo;
final String mPackageName;
private final String mAppDir;
private final String mResDir;
@@ -111,8 +111,7 @@ public final class LoadedApk {
* so MUST NOT call back out to the activity manager.
*/
public LoadedApk(ActivityThread activityThread, ApplicationInfo aInfo,
- CompatibilityInfo compatInfo,
- ActivityThread mainThread, ClassLoader baseLoader,
+ CompatibilityInfo compatInfo, ClassLoader baseLoader,
boolean securityViolation, boolean includeCode) {
mActivityThread = activityThread;
mApplicationInfo = aInfo;
@@ -134,31 +133,17 @@ public final class LoadedApk {
mSecurityViolation = securityViolation;
mIncludeCode = includeCode;
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
-
- if (mAppDir == null) {
- if (ActivityThread.mSystemContext == null) {
- ActivityThread.mSystemContext =
- ContextImpl.createSystemContext(mainThread);
- ResourcesManager resourcesManager = ResourcesManager.getInstance();
- ActivityThread.mSystemContext.getResources().updateConfiguration(
- resourcesManager.getConfiguration(),
- resourcesManager.getDisplayMetricsLocked(
- Display.DEFAULT_DISPLAY, mDisplayAdjustments), compatInfo);
- //Slog.i(TAG, "Created system resources "
- // + mSystemContext.getResources() + ": "
- // + mSystemContext.getResources().getConfiguration());
- }
- mClassLoader = ActivityThread.mSystemContext.getClassLoader();
- mResources = ActivityThread.mSystemContext.getResources();
- }
}
- public LoadedApk(ActivityThread activityThread, String name,
- Context systemContext, ApplicationInfo info, CompatibilityInfo compatInfo) {
+ /**
+ * Create information about the system package.
+ * Must call {@link #installSystemApplicationInfo} later.
+ */
+ LoadedApk(ActivityThread activityThread) {
mActivityThread = activityThread;
- mApplicationInfo = info != null ? info : new ApplicationInfo();
- mApplicationInfo.packageName = name;
- mPackageName = name;
+ mApplicationInfo = new ApplicationInfo();
+ mApplicationInfo.packageName = "android";
+ mPackageName = "android";
mAppDir = null;
mResDir = null;
mOverlayDirs = null;
@@ -169,9 +154,16 @@ public final class LoadedApk {
mBaseClassLoader = null;
mSecurityViolation = false;
mIncludeCode = true;
- mClassLoader = systemContext.getClassLoader();
- mResources = systemContext.getResources();
- mDisplayAdjustments.setCompatibilityInfo(compatInfo);
+ mClassLoader = ClassLoader.getSystemClassLoader();
+ mResources = Resources.getSystem();
+ }
+
+ /**
+ * Sets application info about the system package.
+ */
+ void installSystemApplicationInfo(ApplicationInfo info) {
+ assert info.packageName.equals("android");
+ mApplicationInfo = info;
}
public String getPackageName() {
@@ -513,8 +505,7 @@ public final class LoadedApk {
try {
java.lang.ClassLoader cl = getClassLoader();
- ContextImpl appContext = new ContextImpl();
- appContext.init(this, null, mActivityThread);
+ ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index c63e586..cce6fc4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1778,7 +1778,7 @@ public class Notification implements Parcelable
RemoteViews button = new RemoteViews(mContext.getPackageName(),
tombstone ? R.layout.notification_action_tombstone
: R.layout.notification_action);
- button.setTextViewCompoundDrawables(R.id.action0, action.icon, 0, 0, 0);
+ button.setTextViewCompoundDrawablesRelative(R.id.action0, action.icon, 0, 0, 0);
button.setTextViewText(R.id.action0, action.title);
if (!tombstone) {
button.setOnClickPendingIntent(R.id.action0, action.actionIntent);
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index bdd0adb..45467b8 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -87,23 +87,25 @@ public final class PendingIntent implements Parcelable {
private final IIntentSender mTarget;
/**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: this
- * PendingIntent can only be used once. If set, after
+ * Flag indicating that this PendingIntent can be used only once.
+ * For use with {@link #getActivity}, {@link #getBroadcast}, and
+ * {@link #getService}. <p>If set, after
* {@link #send()} is called on it, it will be automatically
* canceled for you and any future attempt to send through it will fail.
*/
public static final int FLAG_ONE_SHOT = 1<<30;
/**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: if the described PendingIntent does not already
- * exist, then simply return null instead of creating it.
+ * Flag indicating that if the described PendingIntent already
+ * exists, then simply return null instead of creating it.
+ * For use with {@link #getActivity}, {@link #getBroadcast}, and
+ * {@link #getService}.
*/
public static final int FLAG_NO_CREATE = 1<<29;
/**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: if the described PendingIntent already exists,
- * the current one is canceled before generating a new one. You can use
+ * Flag indicating that if the described PendingIntent already exists,
+ * the current one should be canceled before generating a new one.
+ * For use with {@link #getActivity}, {@link #getBroadcast}, and
+ * {@link #getService}. <p>You can use
* this to retrieve a new PendingIntent when you are only changing the
* extra data in the Intent; by canceling the previous pending intent,
* this ensures that only entities given the new data will be able to
@@ -112,10 +114,10 @@ public final class PendingIntent implements Parcelable {
*/
public static final int FLAG_CANCEL_CURRENT = 1<<28;
/**
- * Flag for use with {@link #getActivity}, {@link #getBroadcast}, and
- * {@link #getService}: if the described PendingIntent already exists,
- * then keep it but its replace its extra data with what is in this new
- * Intent. This can be used if you are creating intents where only the
+ * Flag indicating that if the described PendingIntent already exists,
+ * then keep it but replace its extra data with what is in this new
+ * Intent. For use with {@link #getActivity}, {@link #getBroadcast}, and
+ * {@link #getService}. <p>This can be used if you are creating intents where only the
* extras change, and don't care that any entities that received your
* previous PendingIntent will be able to launch it with your new
* extras even if they are not explicitly given to it.
@@ -203,7 +205,7 @@ public final class PendingIntent implements Parcelable {
* <p class="note">For security reasons, the {@link android.content.Intent}
* you supply here should almost always be an <em>explicit intent</em>,
* that is specify an explicit component to be delivered to through
- * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p>
+ * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
*
* @param context The Context in which this PendingIntent should start
* the activity.
@@ -234,7 +236,7 @@ public final class PendingIntent implements Parcelable {
* <p class="note">For security reasons, the {@link android.content.Intent}
* you supply here should almost always be an <em>explicit intent</em>,
* that is specify an explicit component to be delivered to through
- * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p>
+ * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
*
* @param context The Context in which this PendingIntent should start
* the activity.
@@ -326,7 +328,7 @@ public final class PendingIntent implements Parcelable {
* <p class="note">For security reasons, the {@link android.content.Intent} objects
* you supply here should almost always be <em>explicit intents</em>,
* that is specify an explicit component to be delivered to through
- * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p>
+ * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
*
* @param context The Context in which this PendingIntent should start
* the activity.
@@ -376,7 +378,7 @@ public final class PendingIntent implements Parcelable {
* <p class="note">For security reasons, the {@link android.content.Intent} objects
* you supply here should almost always be <em>explicit intents</em>,
* that is specify an explicit component to be delivered to through
- * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p>
+ * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
*
* @param context The Context in which this PendingIntent should start
* the activity.
@@ -446,7 +448,7 @@ public final class PendingIntent implements Parcelable {
* <p class="note">For security reasons, the {@link android.content.Intent}
* you supply here should almost always be an <em>explicit intent</em>,
* that is specify an explicit component to be delivered to through
- * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p>
+ * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
*
* @param context The Context in which this PendingIntent should perform
* the broadcast.
@@ -500,7 +502,7 @@ public final class PendingIntent implements Parcelable {
* <p class="note">For security reasons, the {@link android.content.Intent}
* you supply here should almost always be an <em>explicit intent</em>,
* that is specify an explicit component to be delivered to through
- * {@link Intent#setClass(android.content.Context, Class)} Intent.setClass</p>
+ * {@link Intent#setClass(android.content.Context, Class) Intent.setClass}</p>
*
* @param context The Context in which this PendingIntent should start
* the service.
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index ced72f8..f291e82 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -45,9 +45,7 @@ import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.WindowManager;
import android.view.WindowManagerGlobal;
import java.io.BufferedInputStream;
@@ -294,9 +292,8 @@ public class WallpaperManager {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
- Bitmap bm = BitmapFactory.decodeFileDescriptor(
+ return BitmapFactory.decodeFileDescriptor(
fd.getFileDescriptor(), null, options);
- return generateBitmap(context, bm, width, height);
} catch (OutOfMemoryError e) {
Log.w(TAG, "Can't decode file", e);
} finally {
@@ -323,8 +320,7 @@ public class WallpaperManager {
try {
BitmapFactory.Options options = new BitmapFactory.Options();
- Bitmap bm = BitmapFactory.decodeStream(is, null, options);
- return generateBitmap(context, bm, width, height);
+ return BitmapFactory.decodeStream(is, null, options);
} catch (OutOfMemoryError e) {
Log.w(TAG, "Can't decode stream", e);
} finally {
@@ -1029,62 +1025,4 @@ public class WallpaperManager {
public void clear() throws IOException {
setResource(com.android.internal.R.drawable.default_wallpaper);
}
-
- static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
- if (bm == null) {
- return null;
- }
-
- WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
- DisplayMetrics metrics = new DisplayMetrics();
- wm.getDefaultDisplay().getMetrics(metrics);
- bm.setDensity(metrics.noncompatDensityDpi);
-
- if (width <= 0 || height <= 0
- || (bm.getWidth() == width && bm.getHeight() == height)) {
- return bm;
- }
-
- // This is the final bitmap we want to return.
- try {
- Bitmap newbm = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- newbm.setDensity(metrics.noncompatDensityDpi);
-
- Canvas c = new Canvas(newbm);
- Rect targetRect = new Rect();
- targetRect.right = bm.getWidth();
- targetRect.bottom = bm.getHeight();
-
- int deltaw = width - targetRect.right;
- int deltah = height - targetRect.bottom;
-
- if (deltaw > 0 || deltah > 0) {
- // We need to scale up so it covers the entire area.
- float scale;
- if (deltaw > deltah) {
- scale = width / (float)targetRect.right;
- } else {
- scale = height / (float)targetRect.bottom;
- }
- targetRect.right = (int)(targetRect.right*scale);
- targetRect.bottom = (int)(targetRect.bottom*scale);
- deltaw = width - targetRect.right;
- deltah = height - targetRect.bottom;
- }
-
- targetRect.offset(deltaw/2, deltah/2);
-
- Paint paint = new Paint();
- paint.setFilterBitmap(true);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
- c.drawBitmap(bm, null, targetRect, paint);
-
- bm.recycle();
- c.setBitmap(null);
- return newbm;
- } catch (OutOfMemoryError e) {
- Log.w(TAG, "Can't generate default bitmap", e);
- return bm;
- }
- }
}
diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl
index bb4f5f1..12ee3b6 100644
--- a/core/java/android/app/backup/IBackupManager.aidl
+++ b/core/java/android/app/backup/IBackupManager.aidl
@@ -43,14 +43,14 @@ interface IBackupManager {
void dataChanged(String packageName);
/**
- * Erase all backed-up data for the given package from the storage
+ * Erase all backed-up data for the given package from the given storage
* destination.
*
* Any application can invoke this method for its own package, but
* only callers who hold the android.permission.BACKUP permission
* may invoke it for arbitrary packages.
*/
- void clearBackupData(String packageName);
+ void clearBackupData(String transportName, String packageName);
/**
* Notifies the Backup Manager Service that an agent has become available. This
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index e2bc80a..75b007c 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -20,21 +20,23 @@ import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.os.Binder;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Message;
import android.os.ParcelUuid;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.util.Pair;
+
import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
@@ -214,6 +216,22 @@ public final class BluetoothAdapter {
"android.bluetooth.adapter.action.SCAN_MODE_CHANGED";
/**
+ * Broadcast Action: Indicate BLE Advertising is started.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_BLUETOOTH_ADVERTISING_STARTED =
+ "android.bluetooth.adapter.action.ADVERTISING_STARTED";
+
+ /**
+ * Broadcast Action: Indicated BLE Advertising is stopped.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_BLUETOOTH_ADVERTISING_STOPPED =
+ "android.bluetooth.adapter.action.ADVERTISING_STOPPED";
+
+ /**
* Used as an int extra field in {@link #ACTION_SCAN_MODE_CHANGED}
* intents to request the current scan mode. Possible values are:
* {@link #SCAN_MODE_NONE},
@@ -251,7 +269,6 @@ public final class BluetoothAdapter {
*/
public static final int SCAN_MODE_CONNECTABLE_DISCOVERABLE = 23;
-
/**
* Broadcast Action: The local Bluetooth adapter has started the remote
* device discovery process.
@@ -350,9 +367,27 @@ public final class BluetoothAdapter {
/** The profile is in disconnecting state */
public static final int STATE_DISCONNECTING = 3;
+ /** States for Bluetooth LE advertising */
+ /** @hide */
+ public static final int STATE_ADVERTISE_STARTING = 0;
+ /** @hide */
+ public static final int STATE_ADVERTISE_STARTED = 1;
+ /** @hide */
+ public static final int STATE_ADVERTISE_STOPPING = 2;
+ /** @hide */
+ public static final int STATE_ADVERTISE_STOPPED = 3;
+ /**
+ * Force stopping advertising without callback in case the advertising app dies.
+ * @hide
+ */
+ public static final int STATE_ADVERTISE_FORCE_STOPPING = 4;
+
/** @hide */
public static final String BLUETOOTH_MANAGER_SERVICE = "bluetooth_manager";
+ /** @hide */
+ public static final int ADVERTISE_CALLBACK_SUCCESS = 0;
+
private static final int ADDRESS_LENGTH = 17;
/**
@@ -365,6 +400,10 @@ public final class BluetoothAdapter {
private IBluetooth mService;
private final Map<LeScanCallback, GattCallbackWrapper> mLeScanClients;
+ private BluetoothAdvScanData mBluetoothAdvScanData = null;
+ private GattCallbackWrapper mAdvertisingGattCallback;
+ private final Handler mHandler; // Handler to post the advertise callback to run on main thread.
+ private final Object mLock = new Object();
/**
* Get a handle to the default local Bluetooth adapter.
@@ -400,6 +439,7 @@ public final class BluetoothAdapter {
} catch (RemoteException e) {Log.e(TAG, "", e);}
mManagerService = managerService;
mLeScanClients = new HashMap<LeScanCallback, GattCallbackWrapper>();
+ mHandler = new Handler(Looper.getMainLooper());
}
/**
@@ -438,6 +478,129 @@ public final class BluetoothAdapter {
}
/**
+ * Returns a {@link BluetoothAdvScanData} object representing advertising data.
+ * Data will be reset when bluetooth service is turned off.
+ * @hide
+ */
+ public BluetoothAdvScanData getAdvScanData() {
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported
+ Log.e(TAG, "failed to start, iGatt null");
+ return null;
+ }
+ if (mBluetoothAdvScanData == null) {
+ mBluetoothAdvScanData = new BluetoothAdvScanData(iGatt, BluetoothAdvScanData.AD);
+ }
+ return mBluetoothAdvScanData;
+ } catch (RemoteException e) {
+ Log.e(TAG, "failed to get advScanData, error: " + e);
+ return null;
+ }
+ }
+
+ /**
+ * Interface for BLE advertising callback.
+ *
+ * @hide
+ */
+ public interface AdvertiseCallback {
+ /**
+ * Callback when advertise starts.
+ * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure.
+ */
+ void onAdvertiseStart(int status);
+ /**
+ * Callback when advertise stops.
+ * @param status - {@link #ADVERTISE_CALLBACK_SUCCESS} for success, others for failure.
+ */
+ void onAdvertiseStop(int status);
+ }
+
+ /**
+ * Start BLE advertising using current {@link BluetoothAdvScanData}.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}
+ *
+ * @param callback - {@link AdvertiseCallback}
+ * @return true if BLE advertising succeeds, false otherwise.
+ * @hide
+ */
+ public boolean startAdvertising(final AdvertiseCallback callback) {
+ if (getState() != STATE_ON) return false;
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported.
+ return false;
+ }
+ // Restart/reset advertising packets if advertising is in progress.
+ if (isAdvertising()) {
+ // Invalid advertising callback.
+ if (mAdvertisingGattCallback == null || mAdvertisingGattCallback.mLeHandle == -1) {
+ Log.e(TAG, "failed to restart advertising, invalid callback");
+ return false;
+ }
+ iGatt.startAdvertising(mAdvertisingGattCallback.mLeHandle);
+ // Run the callback from main thread.
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ // callback with status success.
+ callback.onAdvertiseStart(ADVERTISE_CALLBACK_SUCCESS);
+ }
+ });
+ return true;
+ }
+ UUID uuid = UUID.randomUUID();
+ GattCallbackWrapper wrapper =
+ new GattCallbackWrapper(this, null, null, callback);
+ iGatt.registerClient(new ParcelUuid(uuid), wrapper);
+ if (!wrapper.advertiseStarted()) {
+ return false;
+ }
+ synchronized (mLock) {
+ mAdvertisingGattCallback = wrapper;
+ }
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ }
+
+ /**
+ * Stop BLE advertising.
+ *
+ * @param callback - {@link AdvertiseCallback}
+ * @return true if BLE advertising stops, false otherwise.
+ * @hide
+ */
+ public boolean stopAdvertising(AdvertiseCallback callback) {
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ if (iGatt == null) {
+ // BLE is not supported
+ return false;
+ }
+ if (mAdvertisingGattCallback == null) {
+ // no callback.
+ return false;
+ }
+ // Make sure same callback is used for start and stop advertising.
+ if (callback != mAdvertisingGattCallback.mAdvertiseCallback) {
+ Log.e(TAG, "must use the same callback for star/stop advertising");
+ return false;
+ }
+ mAdvertisingGattCallback.stopAdvertising();
+ return true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ return false;
+ }
+ }
+
+ /**
* Return true if Bluetooth is currently enabled and ready for use.
* <p>Equivalent to:
* <code>getBluetoothState() == STATE_ON</code>
@@ -849,6 +1012,23 @@ public final class BluetoothAdapter {
}
/**
+ * Returns whether BLE is currently advertising.
+ * <p>Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}.
+ *
+ * @hide
+ */
+ public boolean isAdvertising() {
+ if (getState() != STATE_ON) return false;
+ try {
+ IBluetoothGatt iGatt = mManagerService.getBluetoothGatt();
+ return iGatt.isAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ }
+ return false;
+ }
+
+ /**
* Return the set of {@link BluetoothDevice} objects that are bonded
* (paired) to the local adapter.
* <p>If Bluetooth state is not {@link #STATE_ON}, this API
@@ -1272,6 +1452,8 @@ public final class BluetoothAdapter {
if (VDBG) Log.d(TAG, "onBluetoothServiceDown: " + mService);
synchronized (mManagerCallback) {
mService = null;
+ // Reset bluetooth adv scan data when Gatt service is down.
+ mBluetoothAdvScanData = null;
for (IBluetoothManagerCallback cb : mProxyServiceStateCallbacks ){
try {
if (cb != null) {
@@ -1547,7 +1729,9 @@ public final class BluetoothAdapter {
private static final int LE_CALLBACK_REG_TIMEOUT = 2000;
private static final int LE_CALLBACK_REG_WAIT_COUNT = 5;
+ private final AdvertiseCallback mAdvertiseCallback;
private final LeScanCallback mLeScanCb;
+
// mLeHandle 0: not registered
// -1: scan stopped
// >0: registered and scan started
@@ -1561,16 +1745,34 @@ public final class BluetoothAdapter {
mLeScanCb = leScanCb;
mScanFilter = uuid;
mLeHandle = 0;
+ mAdvertiseCallback = null;
+ }
+
+ public GattCallbackWrapper(BluetoothAdapter bluetoothAdapter, LeScanCallback leScanCb,
+ UUID[] uuid, AdvertiseCallback callback) {
+ mBluetoothAdapter = new WeakReference<BluetoothAdapter>(bluetoothAdapter);
+ mLeScanCb = leScanCb;
+ mScanFilter = uuid;
+ mLeHandle = 0;
+ mAdvertiseCallback = callback;
}
public boolean scanStarted() {
+ return waitForRegisteration(LE_CALLBACK_REG_WAIT_COUNT);
+ }
+
+ public boolean advertiseStarted() {
+ // Wait for registeration callback.
+ return waitForRegisteration(1);
+ }
+
+ private boolean waitForRegisteration(int maxWaitCount) {
boolean started = false;
synchronized(this) {
if (mLeHandle == -1) return false;
-
int count = 0;
// wait for callback registration and LE scan to start
- while (mLeHandle == 0 && count < LE_CALLBACK_REG_WAIT_COUNT) {
+ while (mLeHandle == 0 && count < maxWaitCount) {
try {
wait(LE_CALLBACK_REG_TIMEOUT);
} catch (InterruptedException e) {
@@ -1583,6 +1785,27 @@ public final class BluetoothAdapter {
return started;
}
+ public void stopAdvertising() {
+ synchronized (this) {
+ if (mLeHandle <= 0) {
+ Log.e(TAG, "Error state, mLeHandle: " + mLeHandle);
+ return;
+ }
+ BluetoothAdapter adapter = mBluetoothAdapter.get();
+ if (adapter != null) {
+ try {
+ IBluetoothGatt iGatt = adapter.getBluetoothManager().getBluetoothGatt();
+ iGatt.stopAdvertising();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to stop advertising" + e);
+ }
+ } else {
+ Log.e(TAG, "stopAdvertising, BluetoothAdapter is null");
+ }
+ notifyAll();
+ }
+ }
+
public void stopLeScan() {
synchronized(this) {
if (mLeHandle <= 0) {
@@ -1624,14 +1847,18 @@ public final class BluetoothAdapter {
BluetoothAdapter adapter = mBluetoothAdapter.get();
if (adapter != null) {
iGatt = adapter.getBluetoothManager().getBluetoothGatt();
- if (mScanFilter == null) {
- iGatt.startScan(mLeHandle, false);
+ if (mAdvertiseCallback != null) {
+ iGatt.startAdvertising(mLeHandle);
} else {
- ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
- for(int i = 0; i != uuids.length; ++i) {
- uuids[i] = new ParcelUuid(mScanFilter[i]);
- }
- iGatt.startScanWithUuids(mLeHandle, false, uuids);
+ if (mScanFilter == null) {
+ iGatt.startScan(mLeHandle, false);
+ } else {
+ ParcelUuid[] uuids = new ParcelUuid[mScanFilter.length];
+ for(int i = 0; i != uuids.length; ++i) {
+ uuids[i] = new ParcelUuid(mScanFilter[i]);
+ }
+ iGatt.startScanWithUuids(mLeHandle, false, uuids);
+ }
}
} else {
Log.e(TAG, "onClientRegistered, BluetoothAdapter null");
@@ -1642,7 +1869,7 @@ public final class BluetoothAdapter {
mLeHandle = -1;
}
if (mLeHandle == -1) {
- // registration succeeded but start scan failed
+ // registration succeeded but start scan or advertise failed
if (iGatt != null) {
try {
iGatt.unregisterClient(mLeHandle);
@@ -1670,7 +1897,7 @@ public final class BluetoothAdapter {
* @hide
*/
public void onScanResult(String address, int rssi, byte[] advData) {
- if (DBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
+ if (VDBG) Log.d(TAG, "onScanResult() - Device=" + address + " RSSI=" +rssi);
// Check null in case the scan has been stopped
synchronized(this) {
@@ -1759,9 +1986,33 @@ public final class BluetoothAdapter {
// no op
}
- public void onListen(int status) {
- // no op
+ public void onAdvertiseStateChange(int advertiseState, int status) {
+ Log.d(TAG, "on advertise call back, state: " + advertiseState + " status: " + status);
+ if (advertiseState == STATE_ADVERTISE_STARTED) {
+ mAdvertiseCallback.onAdvertiseStart(status);
+ } else {
+ synchronized (this) {
+ if (status == ADVERTISE_CALLBACK_SUCCESS) {
+ BluetoothAdapter adapter = mBluetoothAdapter.get();
+ if (adapter != null) {
+ try {
+ IBluetoothGatt iGatt =
+ adapter.getBluetoothManager().getBluetoothGatt();
+ Log.d(TAG, "unregistering client " + mLeHandle);
+ iGatt.unregisterClient(mLeHandle);
+ // Reset advertise app handle.
+ mLeHandle = -1;
+ adapter.mAdvertisingGattCallback = null;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to unregister client" + e);
+ }
+ } else {
+ Log.e(TAG, "cannot unregister client, BluetoothAdapter is null");
+ }
+ }
+ }
+ mAdvertiseCallback.onAdvertiseStop(status);
+ }
}
}
-
}
diff --git a/core/java/android/bluetooth/BluetoothAdvScanData.java b/core/java/android/bluetooth/BluetoothAdvScanData.java
new file mode 100644
index 0000000..df2c256
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothAdvScanData.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.bluetooth;
+import android.os.ParcelUuid;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * This class provides the public APIs to set advertising and scan response data when BLE device
+ * operates in peripheral mode. <br>
+ * The exact format is defined in Bluetooth 4.0 specification, Volume 3, Part C, Section 11
+ * @hide
+ */
+public final class BluetoothAdvScanData {
+
+ /**
+ * Available data types of {@link BluetoothAdvScanData}.
+ */
+ public static final int AD = 0; // Advertising Data
+ public static final int SCAN_RESPONSE = 1; // Scan Response
+ public static final int EIR = 2; // Extended Inquiry Response
+
+ private static final String TAG = "BluetoothAdvScanData";
+
+ /**
+ * Data type of BluetoothAdvScanData.
+ */
+ private final int mDataType;
+ /**
+ * Bluetooth Gatt Service.
+ */
+ private IBluetoothGatt mBluetoothGatt;
+
+ /**
+ * @param mBluetoothGatt
+ * @param dataType
+ */
+ public BluetoothAdvScanData(IBluetoothGatt mBluetoothGatt, int dataType) {
+ this.mBluetoothGatt = mBluetoothGatt;
+ this.mDataType = dataType;
+ }
+
+ /**
+ * @return advertising data type.
+ */
+ public int getDataType() {
+ return mDataType;
+ }
+
+ /**
+ * Set manufactureCode and manufactureData.
+ * Returns true if manufacturer data is set, false if there is no enough room to set
+ * manufacturer data or the data is already set.
+ * @param manufacturerCode - unique identifier for the manufacturer
+ * @param manufacturerData - data associated with the specific manufacturer.
+ */
+ public boolean setManufacturerData(int manufacturerCode, byte[] manufacturerData) {
+ if (mDataType != AD) return false;
+ try {
+ return mBluetoothGatt.setAdvManufacturerCodeAndData(manufacturerCode, manufacturerData);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to set manufacturer id and data.", e);
+ return false;
+ }
+ }
+
+ /**
+ * Set service data. Note the service data can only be set when the data type is {@code AD};
+ * @param serviceData
+ */
+ public boolean setServiceData(byte[] serviceData) {
+
+ if (mDataType != AD) return false;
+ if (serviceData == null) return false;
+ try {
+ return mBluetoothGatt.setAdvServiceData(serviceData);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to set service data.", e);
+ return false;
+ }
+ }
+
+ /**
+ * Returns an immutable list of service uuids that will be advertised.
+ */
+ public List<ParcelUuid> getServiceUuids() {
+ try {
+ return Collections.unmodifiableList(mBluetoothGatt.getAdvServiceUuids());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to get service uuids.", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns manufacturer data.
+ */
+ public byte[] getManufacturerData() {
+ if (mBluetoothGatt == null) return null;
+ try {
+ return mBluetoothGatt.getAdvManufacturerData();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to get manufacturer data.", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns service data.
+ */
+ public byte[] getServiceData() {
+ if (mBluetoothGatt == null) return null;
+ try {
+ return mBluetoothGatt.getAdvServiceData();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to get service data.", e);
+ return null;
+ }
+ }
+
+ /**
+ * Remove manufacturer data based on given manufacturer code.
+ * @param manufacturerCode
+ */
+ public void removeManufacturerCodeAndData(int manufacturerCode) {
+ if (mBluetoothGatt != null) {
+ try {
+ mBluetoothGatt.removeAdvManufacturerCodeAndData(manufacturerCode);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to remove manufacturer : " + manufacturerCode, e);
+ }
+ }
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index a2bb78c..ae6ad3b 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -555,11 +555,12 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
- * Listen command status callback
+ * Advertise state change callback
* @hide
*/
- public void onListen(int status) {
- if (DBG) Log.d(TAG, "onListen() - status=" + status);
+ public void onAdvertiseStateChange(int state, int status) {
+ if (DBG) Log.d(TAG, "onAdvertiseStateChange() - state = "
+ + state + " status=" + status);
}
};
@@ -693,71 +694,6 @@ public final class BluetoothGatt implements BluetoothProfile {
return true;
}
- /**
- * Starts or stops sending of advertisement packages to listen for connection
- * requests from a central devices.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param start Start or stop advertising
- */
- /*package*/ void listen(boolean start) {
- if (mContext == null || !mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
- throw new UnsupportedOperationException("BluetoothGatt#listen is blocked");
- }
- if (DBG) Log.d(TAG, "listen() - start: " + start);
- if (mService == null || mClientIf == 0) return;
-
- try {
- mService.clientListen(mClientIf, start);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
- /**
- * Sets the advertising data contained in the adv. response packet.
- *
- * <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
- *
- * @param advData true to set adv. data, false to set scan response
- * @param includeName Inlucde the name in the adv. response
- * @param includeTxPower Include TX power value
- * @param minInterval Minimum desired scan interval (optional)
- * @param maxInterval Maximum desired scan interval (optional)
- * @param appearance The appearance flags for the device (optional)
- * @param manufacturerData Manufacturer specific data including company ID (optional)
- */
- /*package*/ void setAdvData(boolean advData, boolean includeName, boolean includeTxPower,
- Integer minInterval, Integer maxInterval,
- Integer appearance, Byte[] manufacturerData) {
- if (mContext == null || !mContext.getResources().
- getBoolean(com.android.internal.R.bool.config_bluetooth_le_peripheral_mode_supported)) {
- throw new UnsupportedOperationException("BluetoothGatt#setAdvData is blocked");
- }
- if (DBG) Log.d(TAG, "setAdvData()");
- if (mService == null || mClientIf == 0) return;
-
- byte[] data = new byte[0];
- if (manufacturerData != null) {
- data = new byte[manufacturerData.length];
- for(int i = 0; i != manufacturerData.length; ++i) {
- data[i] = manufacturerData[i];
- }
- }
-
- try {
- mService.setAdvData(mClientIf, !advData,
- includeName, includeTxPower,
- minInterval != null ? minInterval : 0,
- maxInterval != null ? maxInterval : 0,
- appearance != null ? appearance : 0, data);
- } catch (RemoteException e) {
- Log.e(TAG,"",e);
- }
- }
-
/**
* Disconnects an established connection, or cancels a connection attempt
* currently in progress.
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 58ee54f..153215c 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -537,7 +537,7 @@ public final class BluetoothGattServer implements BluetoothProfile {
try {
mService.beginServiceDeclaration(mServerIf, service.getType(),
service.getInstanceId(), service.getHandles(),
- new ParcelUuid(service.getUuid()));
+ new ParcelUuid(service.getUuid()), service.isAdvertisePreferred());
List<BluetoothGattService> includedServices = service.getIncludedServices();
for (BluetoothGattService includedService : includedServices) {
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 1e66369..52bc0f7 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -15,8 +15,6 @@
*/
package android.bluetooth;
-import android.bluetooth.BluetoothDevice;
-
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -82,6 +80,11 @@ public class BluetoothGattService {
protected List<BluetoothGattService> mIncludedServices;
/**
+ * Whether the service uuid should be advertised.
+ */
+ private boolean mAdvertisePreferred;
+
+ /**
* Create a new BluetoothGattService.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
@@ -263,4 +266,20 @@ public class BluetoothGattService {
}
return null;
}
+
+ /**
+ * Returns whether the uuid of the service should be advertised.
+ * @hide
+ */
+ public boolean isAdvertisePreferred() {
+ return mAdvertisePreferred;
+ }
+
+ /**
+ * Set whether the service uuid should be advertised.
+ * @hide
+ */
+ public void setAdvertisePreferred(boolean advertisePreferred) {
+ this.mAdvertisePreferred = advertisePreferred;
+ }
}
diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java
index abdf949..4b28516 100644
--- a/core/java/android/bluetooth/BluetoothUuid.java
+++ b/core/java/android/bluetooth/BluetoothUuid.java
@@ -73,6 +73,9 @@ public final class BluetoothUuid {
public static final ParcelUuid MAS =
ParcelUuid.fromString("00001132-0000-1000-8000-00805F9B34FB");
+ public static final ParcelUuid BASE_UUID =
+ ParcelUuid.fromString("00000000-0000-1000-8000-00805F9B34FB");
+
public static final ParcelUuid[] RESERVED_UUIDS = {
AudioSink, AudioSource, AdvAudioDist, HSP, Handsfree, AvrcpController, AvrcpTarget,
@@ -211,4 +214,17 @@ public final class BluetoothUuid {
long value = (uuid.getMostSignificantBits() & 0x0000FFFF00000000L) >>> 32;
return (int)value;
}
+
+ /**
+ * Check whether the given parcelUuid can be converted to 16 bit bluetooth uuid.
+ * @param parcelUuid
+ * @return true if the parcelUuid can be converted to 16 bit uuid, false otherwise.
+ */
+ public static boolean isShortUuid(ParcelUuid parcelUuid) {
+ UUID uuid = parcelUuid.getUuid();
+ if (uuid.getLeastSignificantBits() != BASE_UUID.getUuid().getLeastSignificantBits()) {
+ return false;
+ }
+ return ((uuid.getMostSignificantBits() & 0xFFFF0000FFFFFFFFL) == 0x1000L);
+ }
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index df393db..784cdcc 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -37,10 +37,15 @@ interface IBluetoothGatt {
void unregisterClient(in int clientIf);
void clientConnect(in int clientIf, in String address, in boolean isDirect);
void clientDisconnect(in int clientIf, in String address);
- void clientListen(in int clientIf, in boolean start);
- void setAdvData(in int clientIf, in boolean setScanRsp, in boolean inclName,
- in boolean inclTxPower, in int minInterval, in int maxInterval,
- in int appearance, in byte[] manufacturerData);
+ void startAdvertising(in int appIf);
+ void stopAdvertising();
+ boolean setAdvServiceData(in byte[] serviceData);
+ byte[] getAdvServiceData();
+ boolean setAdvManufacturerCodeAndData(int manufactureCode, in byte[] manufacturerData);
+ byte[] getAdvManufacturerData();
+ List<ParcelUuid> getAdvServiceUuids();
+ void removeAdvManufacturerCodeAndData(int manufacturerCode);
+ boolean isAdvertising();
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
void readCharacteristic(in int clientIf, in String address, in int srvcType,
@@ -75,7 +80,7 @@ interface IBluetoothGatt {
void serverDisconnect(in int serverIf, in String address);
void beginServiceDeclaration(in int serverIf, in int srvcType,
in int srvcInstanceId, in int minHandles,
- in ParcelUuid srvcId);
+ in ParcelUuid srvcId, boolean advertisePreferred);
void addIncludedService(in int serverIf, in int srvcType,
in int srvcInstanceId, in ParcelUuid srvcId);
void addCharacteristic(in int serverIf, in ParcelUuid charId,
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index 60c297b..7c69a06 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -63,5 +63,5 @@ interface IBluetoothGattCallback {
in int charInstId, in ParcelUuid charUuid,
in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
- void onListen(in int status);
+ oneway void onAdvertiseStateChange(in int advertiseState, in int status);
}
diff --git a/core/java/android/bluetooth/package.html b/core/java/android/bluetooth/package.html
index 200a21b..d9ca4f1 100644
--- a/core/java/android/bluetooth/package.html
+++ b/core/java/android/bluetooth/package.html
@@ -8,17 +8,19 @@ The Bluetooth API supports both "Classic Bluetooth" and Bluetooth Low Energy.</p
<a href="{@docRoot}guide/topics/connectivity/bluetooth.html">Bluetooth</a> guide.
For more information about Bluetooth Low Energy, see the
<a href="{@docRoot}guide/topics/connectivity/bluetooth-le.html">
-Bluetooth Low Energy</a> guide.</p>
+Bluetooth Low Energy</a> (BLE) guide.</p>
{@more}
<p>The Bluetooth APIs let applications:</p>
<ul>
- <li>Scan for other Bluetooth devices (including Bluetooth Low Energy
- devices)</li>
- <li>Query the local Bluetooth adapter for paired Bluetooth devices</li>
- <li>Establish RFCOMM channels/sockets</li>
- <li>Connect to specified sockets on other devices</li>
- <li>Transfer data to and from other devices</li>
+ <li>Scan for other Bluetooth devices (including BLE devices).</li>
+ <li>Query the local Bluetooth adapter for paired Bluetooth devices.</li>
+ <li>Establish RFCOMM channels/sockets.</li>
+ <li>Connect to specified sockets on other devices.</li>
+ <li>Transfer data to and from other devices.</li>
+ <li>Communicate with BLE devices, such as proximity sensors, heart rate
+ monitors, fitness devices, and so on.</li>
+ <li>Act as a GATT client or a GATT server (BLE).</li>
</ul>
<p>
diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java
index 5cb6e77..be35f08 100644
--- a/core/java/android/content/ClipDescription.java
+++ b/core/java/android/content/ClipDescription.java
@@ -87,7 +87,7 @@ public class ClipDescription implements Parcelable {
/**
* Helper to compare two MIME types, where one may be a pattern.
* @param concreteType A fully-specified MIME type.
- * @param desiredType A desired MIME type that may be a pattern such as *\/*.
+ * @param desiredType A desired MIME type that may be a pattern such as *&#47;*.
* @return Returns true if the two MIME types match.
*/
public static boolean compareMimeTypes(String concreteType, String desiredType) {
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 44831fc..02c850b 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -1328,7 +1328,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*
* @param uri The data in the content provider being queried.
* @param mimeTypeFilter The type of data the client desires. May be
- * a pattern, such as *\/* to retrieve all possible data types.
+ * a pattern, such as *&#47;* to retrieve all possible data types.
* @return Returns {@code null} if there are no possible data streams for the
* given mimeTypeFilter. Otherwise returns an array of all available
* concrete MIME types.
@@ -1366,7 +1366,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*
* @param uri The data in the content provider being queried.
* @param mimeTypeFilter The type of data the client desires. May be
- * a pattern, such as *\/*, if the caller does not have specific type
+ * a pattern, such as *&#47;*, if the caller does not have specific type
* requirements; in this case the content provider will pick its best
* type matching the pattern.
* @param opts Additional options from the client. The definitions of
@@ -1427,7 +1427,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*
* @param uri The data in the content provider being queried.
* @param mimeTypeFilter The type of data the client desires. May be
- * a pattern, such as *\/*, if the caller does not have specific type
+ * a pattern, such as *&#47;*, if the caller does not have specific type
* requirements; in this case the content provider will pick its best
* type matching the pattern.
* @param opts Additional options from the client. The definitions of
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 4e6cc92..2bf4d7d 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -344,7 +344,7 @@ public abstract class ContentResolver {
* @param url A Uri identifying content (either a list or specific type),
* using the content:// scheme.
* @param mimeTypeFilter The desired MIME type. This may be a pattern,
- * such as *\/*, to query for all available MIME types that match the
+ * such as *&#47;*, to query for all available MIME types that match the
* pattern.
* @return Returns an array of MIME type strings for all available
* data streams that match the given mimeTypeFilter. If there are none,
@@ -815,7 +815,7 @@ public abstract class ContentResolver {
*
* <p>Note that if this function is called for read-only input (mode is "r")
* on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
- * for you with a MIME type of "*\/*". This allows such callers to benefit
+ * for you with a MIME type of "*&#47;*". This allows such callers to benefit
* from any built-in data conversion that a provider implements.
*
* @param uri The desired URI to open.
@@ -868,7 +868,7 @@ public abstract class ContentResolver {
*
* <p>Note that if this function is called for read-only input (mode is "r")
* on a content: URI, it will instead call {@link #openTypedAssetFileDescriptor}
- * for you with a MIME type of "*\/*". This allows such callers to benefit
+ * for you with a MIME type of "*&#47;*". This allows such callers to benefit
* from any built-in data conversion that a provider implements.
*
* @param uri The desired URI to open.
@@ -993,7 +993,7 @@ public abstract class ContentResolver {
*
* @param uri The desired URI to open.
* @param mimeType The desired MIME type of the returned data. This can
- * be a pattern such as *\/*, which will allow the content provider to
+ * be a pattern such as *&#47;*, which will allow the content provider to
* select a type, though there is no way for you to determine what type
* it is returning.
* @param opts Additional provider-dependent options.
@@ -1026,7 +1026,7 @@ public abstract class ContentResolver {
*
* @param uri The desired URI to open.
* @param mimeType The desired MIME type of the returned data. This can
- * be a pattern such as *\/*, which will allow the content provider to
+ * be a pattern such as *&#47;*, which will allow the content provider to
* select a type, though there is no way for you to determine what type
* it is returning.
* @param opts Additional provider-dependent options.
@@ -1535,7 +1535,7 @@ public abstract class ContentResolver {
* for a whole class of content.
* @param notifyForDescendents If <code>true</code> changes to URIs beginning with <code>uri</code>
* will also cause notifications to be sent. If <code>false</code> only changes to the exact URI
- * specified by <em>uri</em> will cause notifications to be sent. If true, than any URI values
+ * specified by <em>uri</em> will cause notifications to be sent. If <code>true</code>, any URI values
* at or below the specified URI will also trigger a match.
* @param observer The object that receives callbacks when changes occur.
* @see #unregisterContentObserver
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2e2d4b8..a50b650 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -844,7 +844,7 @@ public class Intent implements Parcelable, Cloneable {
* {@link #FLAG_GRANT_WRITE_URI_PERMISSION}, then these flags will also be
* set in the returned chooser intent, with its ClipData set appropriately:
* either a direct reflection of {@link #getClipData()} if that is non-null,
- * or a new ClipData build from {@link #getData()}.
+ * or a new ClipData built from {@link #getData()}.
*
* @param target The Intent that the user will be selecting an activity
* to perform.
@@ -4424,7 +4424,7 @@ public class Intent implements Parcelable, Cloneable {
* Return the {@link ClipData} associated with this Intent. If there is
* none, returns null. See {@link #setClipData} for more information.
*
- * @see #setClipData;
+ * @see #setClipData
*/
public ClipData getClipData() {
return mClipData;
@@ -5440,7 +5440,7 @@ public class Intent implements Parcelable, Cloneable {
* directly used by Intent. Applications should generally rely on the
* MIME type of the Intent itself, not what it may find in the ClipData.
* A common practice is to construct a ClipData for use with an Intent
- * with a MIME type of "*\/*".
+ * with a MIME type of "*&#47;*".
*
* @param clip The new clip to set. May be null to clear the current clip.
*/
@@ -7162,8 +7162,8 @@ public class Intent implements Parcelable, Cloneable {
*
* @param type MIME data type to normalize
* @return normalized MIME data type, or null if the input was null
- * @see {@link #setType}
- * @see {@link #setTypeAndNormalize}
+ * @see #setType
+ * @see #setTypeAndNormalize
*/
public static String normalizeMimeType(String type) {
if (type == null) {
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 111062d..eae4a46 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -45,6 +45,7 @@ import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
@@ -2150,10 +2151,20 @@ public class Camera {
private static final String PIXEL_FORMAT_JPEG = "jpeg";
private static final String PIXEL_FORMAT_BAYER_RGGB = "bayer-rggb";
- private HashMap<String, String> mMap;
+ /**
+ * Order matters: Keys that are {@link #set(String, String) set} later
+ * will take precedence over keys that are set earlier (if the two keys
+ * conflict with each other).
+ *
+ * <p>One example is {@link #setPreviewFpsRange(int, int)} , since it
+ * conflicts with {@link #setPreviewFrameRate(int)} whichever key is set later
+ * is the one that will take precedence.
+ * </p>
+ */
+ private final LinkedHashMap<String, String> mMap;
private Parameters() {
- mMap = new HashMap<String, String>(64);
+ mMap = new LinkedHashMap<String, String>(/*initialCapacity*/64);
}
/**
@@ -2233,7 +2244,7 @@ public class Camera {
return;
}
- mMap.put(key, value);
+ put(key, value);
}
/**
@@ -2243,7 +2254,18 @@ public class Camera {
* @param value the int value of the parameter
*/
public void set(String key, int value) {
- mMap.put(key, Integer.toString(value));
+ put(key, Integer.toString(value));
+ }
+
+ private void put(String key, String value) {
+ /*
+ * Remove the key if it already exists.
+ *
+ * This way setting a new value for an already existing key will always move
+ * that key to be ordered the latest in the map.
+ */
+ mMap.remove(key);
+ mMap.put(key, value);
}
private void set(String key, List<Area> areas) {
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index ac9189d..5f2b5f0 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1056,8 +1056,8 @@ public abstract class SensorManager {
* is mapped.
*
* @param outR
- * the transformed rotation matrix. inR and outR can be the same
- * array, but it is not recommended for performance reason.
+ * the transformed rotation matrix. inR and outR should not be the same
+ * array.
*
* @return <code>true</code> on success. <code>false</code> if the input
* parameters are incorrect, for instance if X and Y define the same
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index d5208d9..093e0e9 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -297,16 +297,31 @@ public final class DisplayManager {
}
/**
- * Initiates a fresh scan of availble Wifi displays.
+ * Starts scanning for available Wifi displays.
* The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast.
* <p>
+ * Calls to this method nest and must be matched by an equal number of calls to
+ * {@link #stopWifiDisplayScan()}.
+ * </p><p>
+ * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
+ * </p>
+ *
+ * @hide
+ */
+ public void startWifiDisplayScan() {
+ mGlobal.startWifiDisplayScan();
+ }
+
+ /**
+ * Stops scanning for available Wifi displays.
+ * <p>
* Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}.
* </p>
*
* @hide
*/
- public void scanWifiDisplays() {
- mGlobal.scanWifiDisplays();
+ public void stopWifiDisplayScan() {
+ mGlobal.stopWifiDisplayScan();
}
/**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 936a086..3417430 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -72,6 +72,8 @@ public final class DisplayManagerGlobal {
private final SparseArray<DisplayInfo> mDisplayInfoCache = new SparseArray<DisplayInfo>();
private int[] mDisplayIdCache;
+ private int mWifiDisplayScanNestCount;
+
private DisplayManagerGlobal(IDisplayManager dm) {
mDm = dm;
}
@@ -267,11 +269,32 @@ public final class DisplayManagerGlobal {
}
}
- public void scanWifiDisplays() {
- try {
- mDm.scanWifiDisplays();
- } catch (RemoteException ex) {
- Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+ public void startWifiDisplayScan() {
+ synchronized (mLock) {
+ if (mWifiDisplayScanNestCount++ == 0) {
+ registerCallbackIfNeededLocked();
+ try {
+ mDm.startWifiDisplayScan();
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+ }
+ }
+ }
+ }
+
+ public void stopWifiDisplayScan() {
+ synchronized (mLock) {
+ if (--mWifiDisplayScanNestCount == 0) {
+ try {
+ mDm.stopWifiDisplayScan();
+ } catch (RemoteException ex) {
+ Log.e(TAG, "Failed to scan for Wifi displays.", ex);
+ }
+ } else if (mWifiDisplayScanNestCount < 0) {
+ Log.wtf(TAG, "Wifi display scan nest count became negative: "
+ + mWifiDisplayScanNestCount);
+ mWifiDisplayScanNestCount = 0;
+ }
}
}
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 6b2c887..68eb13f 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -29,11 +29,14 @@ interface IDisplayManager {
void registerCallback(in IDisplayManagerCallback callback);
- // No permissions required.
- void scanWifiDisplays();
+ // Requires CONFIGURE_WIFI_DISPLAY permission.
+ // The process must have previously registered a callback.
+ void startWifiDisplayScan();
- // Requires CONFIGURE_WIFI_DISPLAY permission to connect to an unknown device.
- // No permissions required to connect to a known device.
+ // Requires CONFIGURE_WIFI_DISPLAY permission.
+ void stopWifiDisplayScan();
+
+ // Requires CONFIGURE_WIFI_DISPLAY permission.
void connectWifiDisplay(String address);
// No permissions required.
@@ -45,6 +48,12 @@ interface IDisplayManager {
// Requires CONFIGURE_WIFI_DISPLAY permission.
void forgetWifiDisplay(String address);
+ // Requires CONFIGURE_WIFI_DISPLAY permission.
+ void pauseWifiDisplay();
+
+ // Requires CONFIGURE_WIFI_DISPLAY permission.
+ void resumeWifiDisplay();
+
// No permissions required.
WifiDisplayStatus getWifiDisplayStatus();
@@ -55,10 +64,4 @@ interface IDisplayManager {
// No permissions required but must be same Uid as the creator.
void releaseVirtualDisplay(in IBinder token);
-
- // Requires CONFIGURE_WIFI_DISPLAY permission.
- void pauseWifiDisplay();
-
- // Requires CONFIGURE_WIFI_DISPLAY permission.
- void resumeWifiDisplay();
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index c78a973..70c8750 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -395,6 +395,8 @@ public class ConnectivityManager {
private final IConnectivityManager mService;
+ private final String mPackageName;
+
/**
* Tests if a given integer represents a valid network type.
* @param networkType the type to be tested
@@ -802,7 +804,7 @@ public class ConnectivityManager {
public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
byte[] address = hostAddress.getAddress();
try {
- return mService.requestRouteToHostAddress(networkType, address);
+ return mService.requestRouteToHostAddress(networkType, address, mPackageName);
} catch (RemoteException e) {
return false;
}
@@ -898,8 +900,9 @@ public class ConnectivityManager {
/**
* {@hide}
*/
- public ConnectivityManager(IConnectivityManager service) {
+ public ConnectivityManager(IConnectivityManager service, String packageName) {
mService = checkNotNull(service, "missing IConnectivityManager");
+ mPackageName = checkNotNull(packageName, "missing package name");
}
/** {@hide} */
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index c1da2e3..4bca7fe 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -71,9 +71,9 @@ interface IConnectivityManager
int stopUsingNetworkFeature(int networkType, in String feature);
- boolean requestRouteToHost(int networkType, int hostAddress);
+ boolean requestRouteToHost(int networkType, int hostAddress, String packageName);
- boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress);
+ boolean requestRouteToHostAddress(int networkType, in byte[] hostAddress, String packageName);
boolean getMobileDataEnabled();
void setMobileDataEnabled(boolean enabled);
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index c106514..21352bf 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -566,6 +566,17 @@ public class MobileDataStateTracker extends BaseNetworkStateTracker {
return false;
}
+
+ public void setInternalDataEnable(boolean enabled) {
+ if (DBG) log("setInternalDataEnable: E enabled=" + enabled);
+ final AsyncChannel channel = mDataConnectionTrackerAc;
+ if (channel != null) {
+ channel.sendMessage(DctConstants.EVENT_SET_INTERNAL_DATA_ENABLE,
+ enabled ? DctConstants.ENABLED : DctConstants.DISABLED);
+ }
+ if (VDBG) log("setInternalDataEnable: X enabled=" + enabled);
+ }
+
@Override
public void setUserDataEnable(boolean enabled) {
if (DBG) log("setUserDataEnable: E enabled=" + enabled);
diff --git a/core/java/android/net/VpnService.java b/core/java/android/net/VpnService.java
index d7dc7f5..7385dff 100644
--- a/core/java/android/net/VpnService.java
+++ b/core/java/android/net/VpnService.java
@@ -151,9 +151,10 @@ public class VpnService extends Service {
}
/**
- * Protect a socket from VPN connections. The socket will be bound to the
- * current default network interface, so its traffic will not be forwarded
- * through VPN. This method is useful if some connections need to be kept
+ * Protect a socket from VPN connections. After protecting, data sent
+ * through this socket will go directly to the underlying network,
+ * so its traffic will not be forwarded through the VPN.
+ * This method is useful if some connections need to be kept
* outside of VPN. For example, a VPN tunnel should protect itself if its
* destination is covered by VPN routes. Otherwise its outgoing packets
* will be sent back to the VPN interface and cause an infinite loop. This
diff --git a/core/java/android/os/AsyncTask.java b/core/java/android/os/AsyncTask.java
index d4a3006..26e09b6 100644
--- a/core/java/android/os/AsyncTask.java
+++ b/core/java/android/os/AsyncTask.java
@@ -610,7 +610,7 @@ public abstract class AsyncTask<Params, Progress, Result> {
* still running. Each call to this method will trigger the execution of
* {@link #onProgressUpdate} on the UI thread.
*
- * {@link #onProgressUpdate} will note be called if the task has been
+ * {@link #onProgressUpdate} will not be called if the task has been
* canceled.
*
* @param values The progress values to update the UI with.
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index c3313c5..b2e0b29 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -49,7 +49,7 @@ public class Build {
/** The manufacturer of the product/hardware. */
public static final String MANUFACTURER = getString("ro.product.manufacturer");
- /** The brand (e.g., carrier) the software is customized for, if any. */
+ /** The consumer-visible brand with which the product/hardware will be associated, if any. */
public static final String BRAND = getString("ro.product.brand");
/** The end-user-visible name for the end product. */
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 21b8ae5..f65b6ba 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -420,7 +420,7 @@ interface INetworkManagementService
/**
* Clear a user range from being associated with an interface.
*/
- void clearDnsInterfaceForUidRange(int uid_start, int uid_end);
+ void clearDnsInterfaceForUidRange(String iface, int uid_start, int uid_end);
/**
* Clear the mappings from pid to Dns interface and from uid range to Dns interface.
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 6650fca..5d55143 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -21,11 +21,11 @@ import android.content.Context;
/**
* Class that operates the vibrator on the device.
* <p>
- * If your process exits, any vibration you started with will stop.
+ * If your process exits, any vibration you started will stop.
* </p>
*
* To obtain an instance of the system vibrator, call
- * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as argument.
+ * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as the argument.
*/
public abstract class Vibrator {
/**
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 7ddfa87..2ab5a91 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -33,6 +33,7 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.TypedValue;
import android.util.Xml;
import android.view.LayoutInflater;
@@ -124,6 +125,8 @@ public abstract class PreferenceActivity extends ListActivity implements
PreferenceManager.OnPreferenceTreeClickListener,
PreferenceFragment.OnPreferenceStartFragmentCallback {
+ private static final String TAG = "PreferenceActivity";
+
// Constants for state save/restore
private static final String HEADERS_TAG = ":android:headers";
private static final String CUR_HEADER_TAG = ":android:cur_header";
@@ -521,9 +524,7 @@ public abstract class PreferenceActivity extends ListActivity implements
int initialTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_TITLE, 0);
int initialShortTitle = getIntent().getIntExtra(EXTRA_SHOW_FRAGMENT_SHORT_TITLE, 0);
- // Restore from headers only if they are supported which
- // is in multi-pane mode.
- if (savedInstanceState != null && !mSinglePane) {
+ if (savedInstanceState != null) {
// We are restarting from a previous saved state; used that to
// initialize, instead of starting fresh.
ArrayList<Header> headers = savedInstanceState.getParcelableArrayList(HEADERS_TAG);
diff --git a/core/java/android/print/PrinterCapabilitiesInfo.java b/core/java/android/print/PrinterCapabilitiesInfo.java
index b615600..806a89d 100644
--- a/core/java/android/print/PrinterCapabilitiesInfo.java
+++ b/core/java/android/print/PrinterCapabilitiesInfo.java
@@ -475,6 +475,12 @@ public final class PrinterCapabilitiesInfo implements Parcelable {
* @param colorModes The color mode bit mask.
* @param defaultColorMode The default color mode.
* @return This builder.
+ * <p>
+ * <strong>Note:</strong> On platform version 19 (Kitkat) specifying
+ * only PrintAttributes#COLOR_MODE_MONOCHROME leads to a print spooler
+ * crash. Hence, you should declare either both color modes or
+ * PrintAttributes#COLOR_MODE_COLOR.
+ * </p>
*
* @throws IllegalArgumentException If color modes contains an invalid
* mode bit or if the default color mode is invalid.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index b16df28..0863368 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -18,6 +18,7 @@ package android.provider;
import android.accounts.Account;
import android.app.Activity;
+import android.content.ActivityNotFoundException;
import android.content.ContentProviderClient;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
@@ -40,6 +41,7 @@ import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Pair;
import android.view.View;
+import android.widget.Toast;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@@ -7981,7 +7983,7 @@ public final class ContactsContract {
// Trigger with obtained rectangle
Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
excludeMimes);
- context.startActivity(intent);
+ startActivityWithErrorToast(context, intent);
}
/**
@@ -8014,7 +8016,16 @@ public final class ContactsContract {
String[] excludeMimes) {
Intent intent = composeQuickContactsIntent(context, target, lookupUri, mode,
excludeMimes);
- context.startActivity(intent);
+ startActivityWithErrorToast(context, intent);
+ }
+
+ private static void startActivityWithErrorToast(Context context, Intent intent) {
+ try {
+ context.startActivity(intent);
+ } catch (ActivityNotFoundException e) {
+ Toast.makeText(context, com.android.internal.R.string.quick_contacts_not_available,
+ Toast.LENGTH_SHORT).show();
+ }
}
}
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 39775b6..6519f7e 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -257,8 +257,6 @@ public final class DocumentsContract {
* {@link #MIME_TYPE_DIR}.
*
* @see #COLUMN_FLAGS
- * @see DocumentsContract#createDocument(ContentResolver, Uri, String,
- * String)
* @see DocumentsProvider#createDocument(String, String, String)
*/
public static final int FLAG_DIR_SUPPORTS_CREATE = 1 << 3;
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 04f3f0a..3810eb3 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5140,6 +5140,12 @@ public final class Settings {
public static final String SMS_SHORT_CODE_RULE = "sms_short_code_rule";
/**
+ * Used to select TCP's default initial receiver window size in segments - defaults to a build config value
+ * @hide
+ */
+ public static final String TCP_DEFAULT_INIT_RWND = "tcp_default_init_rwnd";
+
+ /**
* Used to disable Tethering on a device - defaults to true
* @hide
*/
diff --git a/core/java/android/text/format/Time.java b/core/java/android/text/format/Time.java
index 5ef86b1..f34e746 100644
--- a/core/java/android/text/format/Time.java
+++ b/core/java/android/text/format/Time.java
@@ -512,7 +512,7 @@ public class Time {
* <pre>
* Time time = new Time();
* time.set(4, 10, 2007); // set the date to Nov 4, 2007, 12am
- * time.normalize(); // this sets isDst = 1
+ * time.normalize(false); // this sets isDst = 1
* time.monthDay += 1; // changes the date to Nov 5, 2007, 12am
* millis = time.toMillis(false); // millis is Nov 4, 2007, 11pm
* millis = time.toMillis(true); // millis is Nov 5, 2007, 12am
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index d6e116f..dab853a 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -44,7 +44,7 @@ import com.android.internal.util.ArrayUtils;
* {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
* <code>keyAt(int)</code> with ascending values of the index will return the
* keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)<code>.</p>
+ * order in the case of <code>valueAt(int)</code>.</p>
*/
public class LongSparseArray<E> implements Cloneable {
private static final Object DELETED = new Object();
diff --git a/core/java/android/util/LongSparseLongArray.java b/core/java/android/util/LongSparseLongArray.java
index 87d868b..6654899 100644
--- a/core/java/android/util/LongSparseLongArray.java
+++ b/core/java/android/util/LongSparseLongArray.java
@@ -39,7 +39,7 @@ import java.util.Arrays;
* {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
* <code>keyAt(int)</code> with ascending values of the index will return the
* keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)<code>.</p>
+ * order in the case of <code>valueAt(int)</code>.</p>
*
* @hide
*/
diff --git a/core/java/android/util/SparseArray.java b/core/java/android/util/SparseArray.java
index 6e168a8..46d9d45 100644
--- a/core/java/android/util/SparseArray.java
+++ b/core/java/android/util/SparseArray.java
@@ -44,7 +44,7 @@ import com.android.internal.util.ArrayUtils;
* {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
* <code>keyAt(int)</code> with ascending values of the index will return the
* keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)<code>.</p>
+ * order in the case of <code>valueAt(int)</code>.</p>
*/
public class SparseArray<E> implements Cloneable {
private static final Object DELETED = new Object();
diff --git a/core/java/android/util/SparseBooleanArray.java b/core/java/android/util/SparseBooleanArray.java
index 68487e3..905dcb0 100644
--- a/core/java/android/util/SparseBooleanArray.java
+++ b/core/java/android/util/SparseBooleanArray.java
@@ -38,7 +38,7 @@ import com.android.internal.util.ArrayUtils;
* {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
* <code>keyAt(int)</code> with ascending values of the index will return the
* keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)<code>.</p>
+ * order in the case of <code>valueAt(int)</code>.</p>
*/
public class SparseBooleanArray implements Cloneable {
/**
diff --git a/core/java/android/util/SparseIntArray.java b/core/java/android/util/SparseIntArray.java
index 0835cb0..4f5ca07 100644
--- a/core/java/android/util/SparseIntArray.java
+++ b/core/java/android/util/SparseIntArray.java
@@ -37,7 +37,7 @@ import com.android.internal.util.ArrayUtils;
* {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
* <code>keyAt(int)</code> with ascending values of the index will return the
* keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)<code>.</p>
+ * order in the case of <code>valueAt(int)</code>.</p>
*/
public class SparseIntArray implements Cloneable {
private int[] mKeys;
diff --git a/core/java/android/util/SparseLongArray.java b/core/java/android/util/SparseLongArray.java
index 62c1c0d..39fc8a3 100644
--- a/core/java/android/util/SparseLongArray.java
+++ b/core/java/android/util/SparseLongArray.java
@@ -37,7 +37,7 @@ import com.android.internal.util.ArrayUtils;
* {@link #keyAt(int)} and {@link #valueAt(int)}. Iterating over the keys using
* <code>keyAt(int)</code> with ascending values of the index will return the
* keys in ascending order, or the values corresponding to the keys in ascending
- * order in the case of <code>valueAt(int)<code>.</p>
+ * order in the case of <code>valueAt(int)</code>.</p>
*/
public class SparseLongArray implements Cloneable {
private int[] mKeys;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index bdf4141..ef60755 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -6543,7 +6543,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @attr ref android.R.styleable#View_filterTouchesWhenObscured
*/
public void setFilterTouchesWhenObscured(boolean enabled) {
- setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
+ setFlags(enabled ? FILTER_TOUCHES_WHEN_OBSCURED : 0,
FILTER_TOUCHES_WHEN_OBSCURED);
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index c3f064f..e67659c 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -212,6 +212,14 @@ public class ViewConfiguration {
*/
private static final int OVERFLING_DISTANCE = 6;
+ /**
+ * Configuration values for overriding {@link #hasPermanentMenuKey()} behavior.
+ * These constants must match the definition in res/values/config.xml.
+ */
+ private static final int HAS_PERMANENT_MENU_KEY_AUTODETECT = 0;
+ private static final int HAS_PERMANENT_MENU_KEY_TRUE = 1;
+ private static final int HAS_PERMANENT_MENU_KEY_FALSE = 2;
+
private final int mEdgeSlop;
private final int mFadingEdgeLength;
private final int mMinimumFlingVelocity;
@@ -296,12 +304,31 @@ public class ViewConfiguration {
mOverflingDistance = (int) (sizeAndDensity * OVERFLING_DISTANCE + 0.5f);
if (!sHasPermanentMenuKeySet) {
- IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
- try {
- sHasPermanentMenuKey = !wm.hasNavigationBar();
- sHasPermanentMenuKeySet = true;
- } catch (RemoteException ex) {
- sHasPermanentMenuKey = false;
+ final int configVal = res.getInteger(
+ com.android.internal.R.integer.config_overrideHasPermanentMenuKey);
+
+ switch (configVal) {
+ default:
+ case HAS_PERMANENT_MENU_KEY_AUTODETECT: {
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+ try {
+ sHasPermanentMenuKey = !wm.hasNavigationBar();
+ sHasPermanentMenuKeySet = true;
+ } catch (RemoteException ex) {
+ sHasPermanentMenuKey = false;
+ }
+ }
+ break;
+
+ case HAS_PERMANENT_MENU_KEY_TRUE:
+ sHasPermanentMenuKey = true;
+ sHasPermanentMenuKeySet = true;
+ break;
+
+ case HAS_PERMANENT_MENU_KEY_FALSE:
+ sHasPermanentMenuKey = false;
+ sHasPermanentMenuKeySet = true;
+ break;
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 3fd2aa9..5b2a452 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -232,8 +232,6 @@ public final class ViewRootImpl implements ViewParent,
InputStage mFirstInputStage;
InputStage mFirstPostImeInputStage;
- boolean mFlipControllerFallbackKeys;
-
boolean mWindowAttributesChanged = false;
int mWindowAttributesChangesFlag = 0;
@@ -370,8 +368,6 @@ public final class ViewRootImpl implements ViewParent,
mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
mChoreographer = Choreographer.getInstance();
- mFlipControllerFallbackKeys =
- context.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mAttachInfo.mScreenOn = powerManager.isScreenOn();
@@ -2912,11 +2908,8 @@ public final class ViewRootImpl implements ViewParent,
mView.dispatchConfigurationChanged(config);
}
}
-
- mFlipControllerFallbackKeys =
- mContext.getResources().getBoolean(R.bool.flip_controller_fallback_keys);
}
-
+
/**
* Return true if child is an ancestor of parent, (or equal to the parent).
*/
@@ -3985,7 +3978,6 @@ public final class ViewRootImpl implements ViewParent,
private final SyntheticJoystickHandler mJoystick = new SyntheticJoystickHandler();
private final SyntheticTouchNavigationHandler mTouchNavigation =
new SyntheticTouchNavigationHandler();
- private final SyntheticKeyHandler mKeys = new SyntheticKeyHandler();
public SyntheticInputStage() {
super(null);
@@ -4008,12 +4000,7 @@ public final class ViewRootImpl implements ViewParent,
mTouchNavigation.process(event);
return FINISH_HANDLED;
}
- } else if (q.mEvent instanceof KeyEvent) {
- if (mKeys.process((KeyEvent) q.mEvent)) {
- return FINISH_HANDLED;
- }
}
-
return FORWARD;
}
@@ -4843,63 +4830,6 @@ public final class ViewRootImpl implements ViewParent,
};
}
- final class SyntheticKeyHandler {
-
- public boolean process(KeyEvent event) {
- // In some locales (like Japan) controllers use B for confirm and A for back, rather
- // than vice versa, so we need to special case this here since the input system itself
- // is not locale-aware.
- int keyCode;
- switch(event.getKeyCode()) {
- case KeyEvent.KEYCODE_BUTTON_A:
- case KeyEvent.KEYCODE_BUTTON_C:
- case KeyEvent.KEYCODE_BUTTON_X:
- case KeyEvent.KEYCODE_BUTTON_Z:
- keyCode = mFlipControllerFallbackKeys ?
- KeyEvent.KEYCODE_BACK : KeyEvent.KEYCODE_DPAD_CENTER;
- break;
- case KeyEvent.KEYCODE_BUTTON_B:
- case KeyEvent.KEYCODE_BUTTON_Y:
- keyCode = mFlipControllerFallbackKeys ?
- KeyEvent.KEYCODE_DPAD_CENTER : KeyEvent.KEYCODE_BACK;
- break;
- case KeyEvent.KEYCODE_BUTTON_THUMBL:
- case KeyEvent.KEYCODE_BUTTON_THUMBR:
- case KeyEvent.KEYCODE_BUTTON_START:
- case KeyEvent.KEYCODE_BUTTON_1:
- case KeyEvent.KEYCODE_BUTTON_2:
- case KeyEvent.KEYCODE_BUTTON_3:
- case KeyEvent.KEYCODE_BUTTON_4:
- case KeyEvent.KEYCODE_BUTTON_5:
- case KeyEvent.KEYCODE_BUTTON_6:
- case KeyEvent.KEYCODE_BUTTON_7:
- case KeyEvent.KEYCODE_BUTTON_8:
- case KeyEvent.KEYCODE_BUTTON_9:
- case KeyEvent.KEYCODE_BUTTON_10:
- case KeyEvent.KEYCODE_BUTTON_11:
- case KeyEvent.KEYCODE_BUTTON_12:
- case KeyEvent.KEYCODE_BUTTON_13:
- case KeyEvent.KEYCODE_BUTTON_14:
- case KeyEvent.KEYCODE_BUTTON_15:
- case KeyEvent.KEYCODE_BUTTON_16:
- keyCode = KeyEvent.KEYCODE_DPAD_CENTER;
- break;
- case KeyEvent.KEYCODE_BUTTON_SELECT:
- case KeyEvent.KEYCODE_BUTTON_MODE:
- keyCode = KeyEvent.KEYCODE_MENU;
- default:
- return false;
- }
-
- enqueueInputEvent(new KeyEvent(event.getDownTime(), event.getEventTime(),
- event.getAction(), keyCode, event.getRepeatCount(), event.getMetaState(),
- event.getDeviceId(), event.getScanCode(),
- event.getFlags() | KeyEvent.FLAG_FALLBACK, event.getSource()));
- return true;
- }
-
- }
-
/**
* Returns true if the key is used for keyboard navigation.
* @param keyEvent The key event.
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index f0e6677..52f9c0b 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -311,7 +311,6 @@ public class VolumePanel extends Handler implements OnSeekBarChangeListener, Vie
lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
lp.width = LayoutParams.WRAP_CONTENT;
lp.height = LayoutParams.WRAP_CONTENT;
- lp.privateFlags |= LayoutParams.PRIVATE_FLAG_FORCE_SHOW_NAV_BAR;
window.setAttributes(lp);
window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL
| LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 0ce4da5..53a4c0d0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1063,13 +1063,6 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_SHOW_FOR_ALL_USERS = 0x00000010;
/**
- * Special flag for the volume overlay: force the window manager out of "hide nav bar"
- * mode while the window is on screen.
- *
- * {@hide} */
- public static final int PRIVATE_FLAG_FORCE_SHOW_NAV_BAR = 0x00000020;
-
- /**
* Never animate position changes of the window.
*
* {@hide} */
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 5bc39f1..d53bb74 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -686,6 +686,15 @@ public class WebView extends AbsoluteLayout
}
/**
+ * Used only by internal tests to free up memory.
+ *
+ * @hide
+ */
+ public static void freeMemoryForTests() {
+ getFactory().getStatics().freeMemoryForTests();
+ }
+
+ /**
* Informs WebView of the network state. This is used to set
* the JavaScript property window.navigator.isOnline and
* generates the online/offline event as specified in HTML5, sec. 5.7.7
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index 9d9d882..e391aaf 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -50,6 +50,11 @@ public interface WebViewFactoryProvider {
String getDefaultUserAgent(Context context);
/**
+ * Used for tests only.
+ */
+ void freeMemoryForTests();
+
+ /**
* Implements the API method:
* {@link android.webkit.WebView#setWebContentsDebuggingEnabled(boolean) }
*/
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 092f474..25a43a6 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -723,7 +723,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*
* @param view The view whose scroll state is being reported
*
- * @param scrollState The current scroll state. One of {@link #SCROLL_STATE_IDLE},
+ * @param scrollState The current scroll state. One of
* {@link #SCROLL_STATE_TOUCH_SCROLL} or {@link #SCROLL_STATE_IDLE}.
*/
public void onScrollStateChanged(AbsListView view, int scrollState);
@@ -2076,22 +2076,23 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
mInLayout = true;
+ final int childCount = getChildCount();
if (changed) {
- int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
getChildAt(i).forceLayout();
}
mRecycler.markChildrenDirty();
}
- if (mFastScroller != null && (mItemCount != mOldItemCount || mDataChanged)) {
- mFastScroller.onItemCountChanged(mItemCount);
- }
-
layoutChildren();
mInLayout = false;
mOverscrollMax = (b - t) / OVERSCROLL_LIMIT_DIVISOR;
+
+ // TODO: Move somewhere sane. This doesn't belong in onLayout().
+ if (mFastScroller != null) {
+ mFastScroller.onItemCountChanged(getChildCount(), mItemCount);
+ }
}
/**
@@ -2228,26 +2229,34 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "obtainView");
isScrap[0] = false;
- View scrapView;
- scrapView = mRecycler.getTransientStateView(position);
- if (scrapView == null) {
- scrapView = mRecycler.getScrapView(position);
- }
+ // Check whether we have a transient state view. Attempt to re-bind the
+ // data and discard the view if we fail.
+ final View transientView = mRecycler.getTransientStateView(position);
+ if (transientView != null) {
+ final LayoutParams params = (LayoutParams) transientView.getLayoutParams();
- View child;
- if (scrapView != null) {
- child = mAdapter.getView(position, scrapView, this);
+ // If the view type hasn't changed, attempt to re-bind the data.
+ if (params.viewType == mAdapter.getItemViewType(position)) {
+ final View updatedView = mAdapter.getView(position, transientView, this);
- if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
- child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
+ // If we failed to re-bind the data, scrap the obtained view.
+ if (updatedView != transientView) {
+ mRecycler.addScrapView(updatedView, position);
+ }
}
+ // Scrap view implies temporary detachment.
+ isScrap[0] = true;
+ return transientView;
+ }
+
+ final View scrapView = mRecycler.getScrapView(position);
+ final View child = mAdapter.getView(position, scrapView, this);
+ if (scrapView != null) {
if (child != scrapView) {
+ // Failed to re-bind the data, return scrap to the heap.
mRecycler.addScrapView(scrapView, position);
- if (mCacheColorHint != 0) {
- child.setDrawingCacheBackgroundColor(mCacheColorHint);
- }
} else {
isScrap[0] = true;
@@ -2259,16 +2268,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
child.dispatchFinishTemporaryDetach();
}
- } else {
- child = mAdapter.getView(position, null, this);
+ }
- if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
- child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
- }
+ if (mCacheColorHint != 0) {
+ child.setDrawingCacheBackgroundColor(mCacheColorHint);
+ }
- if (mCacheColorHint != 0) {
- child.setDrawingCacheBackgroundColor(mCacheColorHint);
- }
+ if (child.getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+ child.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
if (mAdapterHasStableIds) {
@@ -6562,12 +6569,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
}
- if (mTransientStateViews != null) {
- mTransientStateViews.clear();
- }
- if (mTransientStateViewsById != null) {
- mTransientStateViewsById.clear();
- }
+
+ clearTransientStateViews();
}
/**
@@ -6634,14 +6637,26 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
/**
- * Dump any currently saved views with transient state.
+ * Dumps and fully detaches any currently saved views with transient
+ * state.
*/
void clearTransientStateViews() {
- if (mTransientStateViews != null) {
- mTransientStateViews.clear();
+ final SparseArray<View> viewsByPos = mTransientStateViews;
+ if (viewsByPos != null) {
+ final int N = viewsByPos.size();
+ for (int i = 0; i < N; i++) {
+ removeDetachedView(viewsByPos.valueAt(i), false);
+ }
+ viewsByPos.clear();
}
- if (mTransientStateViewsById != null) {
- mTransientStateViewsById.clear();
+
+ final LongSparseArray<View> viewsById = mTransientStateViewsById;
+ if (viewsById != null) {
+ final int N = viewsById.size();
+ for (int i = 0; i < N; i++) {
+ removeDetachedView(viewsById.valueAt(i), false);
+ }
+ viewsById.clear();
}
}
@@ -6766,44 +6781,48 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (victim != null) {
final AbsListView.LayoutParams lp
= (AbsListView.LayoutParams) victim.getLayoutParams();
- int whichScrap = lp.viewType;
+ final int whichScrap = lp.viewType;
activeViews[i] = null;
- final boolean scrapHasTransientState = victim.hasTransientState();
- if (!shouldRecycleViewType(whichScrap) || scrapHasTransientState) {
- // Do not move views that should be ignored
- if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER &&
- scrapHasTransientState) {
+ if (victim.hasTransientState()) {
+ // Store views with transient state for later use.
+ victim.dispatchStartTemporaryDetach();
+
+ if (mAdapter != null && mAdapterHasStableIds) {
+ if (mTransientStateViewsById == null) {
+ mTransientStateViewsById = new LongSparseArray<View>();
+ }
+ long id = mAdapter.getItemId(mFirstActivePosition + i);
+ mTransientStateViewsById.put(id, victim);
+ } else if (!mDataChanged) {
+ if (mTransientStateViews == null) {
+ mTransientStateViews = new SparseArray<View>();
+ }
+ mTransientStateViews.put(mFirstActivePosition + i, victim);
+ } else if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
+ // The data has changed, we can't keep this view.
removeDetachedView(victim, false);
}
- if (scrapHasTransientState) {
- if (mAdapter != null && mAdapterHasStableIds) {
- if (mTransientStateViewsById == null) {
- mTransientStateViewsById = new LongSparseArray<View>();
- }
- long id = mAdapter.getItemId(mFirstActivePosition + i);
- mTransientStateViewsById.put(id, victim);
- } else {
- if (mTransientStateViews == null) {
- mTransientStateViews = new SparseArray<View>();
- }
- mTransientStateViews.put(mFirstActivePosition + i, victim);
- }
+ } else if (!shouldRecycleViewType(whichScrap)) {
+ // Discard non-recyclable views except headers/footers.
+ if (whichScrap != ITEM_VIEW_TYPE_HEADER_OR_FOOTER) {
+ removeDetachedView(victim, false);
+ }
+ } else {
+ // Store everything else on the appropriate scrap heap.
+ if (multipleScraps) {
+ scrapViews = mScrapViews[whichScrap];
}
- continue;
- }
- if (multipleScraps) {
- scrapViews = mScrapViews[whichScrap];
- }
- victim.dispatchStartTemporaryDetach();
- lp.scrappedFromPosition = mFirstActivePosition + i;
- scrapViews.add(victim);
+ victim.dispatchStartTemporaryDetach();
+ lp.scrappedFromPosition = mFirstActivePosition + i;
+ scrapViews.add(victim);
- victim.setAccessibilityDelegate(null);
- if (hasListener) {
- mRecyclerListener.onMovedToScrapHeap(victim);
+ victim.setAccessibilityDelegate(null);
+ if (hasListener) {
+ mRecyclerListener.onMovedToScrapHeap(victim);
+ }
}
}
}
@@ -6812,8 +6831,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
/**
- * Makes sure that the size of mScrapViews does not exceed the size of mActiveViews.
- * (This can happen if an adapter does not recycle its views).
+ * Makes sure that the size of mScrapViews does not exceed the size of
+ * mActiveViews, which can happen if an adapter does not recycle its
+ * views. Removes cached transient state views that no longer have
+ * transient state.
*/
private void pruneScrapViews() {
final int maxViews = mActiveViews.length;
@@ -6829,20 +6850,25 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
- if (mTransientStateViews != null) {
- for (int i = 0; i < mTransientStateViews.size(); i++) {
- final View v = mTransientStateViews.valueAt(i);
+ final SparseArray<View> transViewsByPos = mTransientStateViews;
+ if (transViewsByPos != null) {
+ for (int i = 0; i < transViewsByPos.size(); i++) {
+ final View v = transViewsByPos.valueAt(i);
if (!v.hasTransientState()) {
- mTransientStateViews.removeAt(i);
+ removeDetachedView(v, false);
+ transViewsByPos.removeAt(i);
i--;
}
}
}
- if (mTransientStateViewsById != null) {
- for (int i = 0; i < mTransientStateViewsById.size(); i++) {
- final View v = mTransientStateViewsById.valueAt(i);
+
+ final LongSparseArray<View> transViewsById = mTransientStateViewsById;
+ if (transViewsById != null) {
+ for (int i = 0; i < transViewsById.size(); i++) {
+ final View v = transViewsById.valueAt(i);
if (!v.hasTransientState()) {
- mTransientStateViewsById.removeAt(i);
+ removeDetachedView(v, false);
+ transViewsById.removeAt(i);
i--;
}
}
diff --git a/core/java/android/widget/CalendarView.java b/core/java/android/widget/CalendarView.java
index 0957ab4..e90b460 100644
--- a/core/java/android/widget/CalendarView.java
+++ b/core/java/android/widget/CalendarView.java
@@ -1210,35 +1210,38 @@ public class CalendarView extends FrameLayout {
child = (WeekView) view.getChildAt(offset);
}
- // Find out which month we're moving into
- int month;
- if (mIsScrollingUp) {
- month = child.getMonthOfFirstWeekDay();
- } else {
- month = child.getMonthOfLastWeekDay();
- }
-
- // And how it relates to our current highlighted month
- int monthDiff;
- if (mCurrentMonthDisplayed == 11 && month == 0) {
- monthDiff = 1;
- } else if (mCurrentMonthDisplayed == 0 && month == 11) {
- monthDiff = -1;
- } else {
- monthDiff = month - mCurrentMonthDisplayed;
- }
-
- // Only switch months if we're scrolling away from the currently
- // selected month
- if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
- Calendar firstDay = child.getFirstDay();
+ if (child != null) {
+ // Find out which month we're moving into
+ int month;
if (mIsScrollingUp) {
- firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+ month = child.getMonthOfFirstWeekDay();
} else {
- firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+ month = child.getMonthOfLastWeekDay();
+ }
+
+ // And how it relates to our current highlighted month
+ int monthDiff;
+ if (mCurrentMonthDisplayed == 11 && month == 0) {
+ monthDiff = 1;
+ } else if (mCurrentMonthDisplayed == 0 && month == 11) {
+ monthDiff = -1;
+ } else {
+ monthDiff = month - mCurrentMonthDisplayed;
+ }
+
+ // Only switch months if we're scrolling away from the currently
+ // selected month
+ if ((!mIsScrollingUp && monthDiff > 0) || (mIsScrollingUp && monthDiff < 0)) {
+ Calendar firstDay = child.getFirstDay();
+ if (mIsScrollingUp) {
+ firstDay.add(Calendar.DAY_OF_MONTH, -DAYS_PER_WEEK);
+ } else {
+ firstDay.add(Calendar.DAY_OF_MONTH, DAYS_PER_WEEK);
+ }
+ setMonthDisplayed(firstDay);
}
- setMonthDisplayed(firstDay);
}
+
mPreviousScrollPosition = currScroll;
mPreviousScrollState = mCurrentScrollState;
}
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 01ac8fd..4379bf6 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -224,6 +224,8 @@ class FastScroller {
mHasPendingDrag = false;
}
};
+ private int mOldItemCount;
+ private int mOldChildCount;
/**
* Used to delay hiding fast scroll decorations.
@@ -248,6 +250,8 @@ class FastScroller {
public FastScroller(AbsListView listView) {
mList = listView;
mOverlay = listView.getOverlay();
+ mOldItemCount = listView.getCount();
+ mOldChildCount = listView.getChildCount();
final Context context = listView.getContext();
mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
@@ -258,6 +262,7 @@ class FastScroller {
final ImageView trackImage = new ImageView(context);
mTrackImage = trackImage;
+ updateLongList(mOldChildCount, mOldItemCount);
int width = 0;
// Add track to overlay if it has an image.
@@ -445,20 +450,23 @@ class FastScroller {
updateLayout();
}
- public void onItemCountChanged(int totalItemCount) {
- final int visibleItemCount = mList.getChildCount();
- final boolean hasMoreItems = totalItemCount - visibleItemCount > 0;
- if (hasMoreItems && mState != STATE_DRAGGING) {
- final int firstVisibleItem = mList.getFirstVisiblePosition();
- setThumbPos(getPosFromItemCount(firstVisibleItem, visibleItemCount, totalItemCount));
- }
+ public void onItemCountChanged(int childCount, int itemCount) {
+ if (mOldItemCount != itemCount || mOldChildCount != childCount) {
+ mOldItemCount = itemCount;
+ mOldChildCount = childCount;
- updateLongList(visibleItemCount, totalItemCount);
+ final boolean hasMoreItems = itemCount - childCount > 0;
+ if (hasMoreItems && mState != STATE_DRAGGING) {
+ final int firstVisibleItem = mList.getFirstVisiblePosition();
+ setThumbPos(getPosFromItemCount(firstVisibleItem, childCount, itemCount));
+ }
+
+ updateLongList(childCount, itemCount);
+ }
}
- private void updateLongList(int visibleItemCount, int totalItemCount) {
- final boolean longList = visibleItemCount > 0
- && totalItemCount / visibleItemCount >= MIN_PAGES;
+ private void updateLongList(int childCount, int itemCount) {
+ final boolean longList = childCount > 0 && itemCount / childCount >= MIN_PAGES;
if (mLongList != longList) {
mLongList = longList;
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 7daf798..f05179b 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -563,7 +563,7 @@ public class ImageView extends View {
}
/** Return the view's optional matrix. This is applied to the
- view's drawable when it is drawn. If there is not matrix,
+ view's drawable when it is drawn. If there is no matrix,
this method will return an identity matrix.
Do not change this matrix in place but make a copy.
If you want a different matrix applied to the drawable,
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index 5663959..be20d2d 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1330,7 +1330,7 @@ public class PopupWindow {
/**
* Updates the state of the popup window, if it is currently being displayed,
- * from the currently set state. This include:
+ * from the currently set state. This includes:
* {@link #setClippingEnabled(boolean)}, {@link #setFocusable(boolean)},
* {@link #setIgnoreCheekPress()}, {@link #setInputMethodMode(int)},
* {@link #setTouchable(boolean)}, and {@link #setAnimationStyle(int)}.
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 5392a96..6a369a6 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -308,6 +308,11 @@ public class ProgressBar extends View {
mMirrorForRtl = a.getBoolean(R.styleable.ProgressBar_mirrorForRtl, mMirrorForRtl);
a.recycle();
+
+ // If not explicitly specified this view is important for accessibility.
+ if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+ setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
+ }
}
/**
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 62afd2e..bdaaa01 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -266,7 +266,7 @@ public class ShareActionProvider extends ActionProvider {
* Intent shareIntent = new Intent(Intent.ACTION_SEND);
* shareIntent.setType("image/*");
* Uri uri = Uri.fromFile(new File(getFilesDir(), "foo.jpg"));
- * shareIntent.putExtra(Intent.EXTRA_STREAM, uri.toString());</pre>
+ * shareIntent.putExtra(Intent.EXTRA_STREAM, uri));</pre>
*
* @param shareIntent The share intent.
*
diff --git a/core/java/android/widget/SpellChecker.java b/core/java/android/widget/SpellChecker.java
index b204dfd..1cda631 100644
--- a/core/java/android/widget/SpellChecker.java
+++ b/core/java/android/widget/SpellChecker.java
@@ -731,10 +731,14 @@ public class SpellChecker implements SpellCheckerSessionListener {
}
}
- if (scheduleOtherSpellCheck) {
+ if (scheduleOtherSpellCheck && wordStart <= end) {
// Update range span: start new spell check from last wordStart
setRangeSpan(editable, wordStart, end);
} else {
+ if (DBG && scheduleOtherSpellCheck) {
+ Log.w(TAG, "Trying to schedule spellcheck for invalid region, from "
+ + wordStart + " to " + end);
+ }
removeRangeSpan(editable);
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3f35875..5ece016 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8667,6 +8667,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
super.onRtlPropertiesChanged(layoutDirection);
mTextDir = getTextDirectionHeuristic();
+
+ if (mLayout != null) {
+ checkForRelayout();
+ }
}
TextDirectionHeuristic getTextDirectionHeuristic() {
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index a87992a..a13a1cb 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -1004,7 +1004,7 @@ public final class ProcessStats implements Parcelable {
for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
ProcessState ps = pkgState.mProcesses.valueAt(iproc);
if (ps.isInUse() || ps.mCommonProcess.isInUse()) {
- pkgState.mProcesses.valueAt(iproc).resetSafely(now);
+ ps.resetSafely(now);
} else {
pkgState.mProcesses.valueAt(iproc).makeDead();
pkgState.mProcesses.removeAt(iproc);
@@ -1013,7 +1013,7 @@ public final class ProcessStats implements Parcelable {
for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
ServiceState ss = pkgState.mServices.valueAt(isvc);
if (ss.isInUse()) {
- pkgState.mServices.valueAt(isvc).resetSafely(now);
+ ss.resetSafely(now);
} else {
pkgState.mServices.removeAt(isvc);
}
@@ -3014,7 +3014,7 @@ public final class ProcessStats implements Parcelable {
}
public boolean isInUse() {
- return mOwner != null;
+ return mOwner != null || mRestarting;
}
void add(ServiceState other) {
diff --git a/core/java/com/android/internal/content/PackageMonitor.java b/core/java/com/android/internal/content/PackageMonitor.java
index ab871fb..942995b 100644
--- a/core/java/com/android/internal/content/PackageMonitor.java
+++ b/core/java/com/android/internal/content/PackageMonitor.java
@@ -372,23 +372,25 @@ public abstract class PackageMonitor extends android.content.BroadcastReceiver {
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
mAppearingPackages = pkgList;
- mChangeType = PACKAGE_TEMPORARY_CHANGE;
+ mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)
+ ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE;
mSomePackagesChanged = true;
if (pkgList != null) {
onPackagesAvailable(pkgList);
for (int i=0; i<pkgList.length; i++) {
- onPackageAppeared(pkgList[i], PACKAGE_TEMPORARY_CHANGE);
+ onPackageAppeared(pkgList[i], mChangeType);
}
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
String[] pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
mDisappearingPackages = pkgList;
- mChangeType = PACKAGE_TEMPORARY_CHANGE;
+ mChangeType = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)
+ ? PACKAGE_UPDATING : PACKAGE_TEMPORARY_CHANGE;
mSomePackagesChanged = true;
if (pkgList != null) {
onPackagesUnavailable(pkgList);
for (int i=0; i<pkgList.length; i++) {
- onPackageDisappeared(pkgList[i], PACKAGE_TEMPORARY_CHANGE);
+ onPackageDisappeared(pkgList[i], mChangeType);
}
}
}
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index bee1391..3d97d0c 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -192,10 +192,16 @@ public class ZygoteInit {
static void closeServerSocket() {
try {
if (sServerSocket != null) {
+ FileDescriptor fd = sServerSocket.getFileDescriptor();
sServerSocket.close();
+ if (fd != null) {
+ Libcore.os.close(fd);
+ }
}
} catch (IOException ex) {
Log.e(TAG, "Zygote: error closing sockets", ex);
+ } catch (libcore.io.ErrnoException ex) {
+ Log.e(TAG, "Zygote: error closing descriptor", ex);
}
sServerSocket = null;
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 12ced68..3724a08 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -73,5 +73,5 @@ interface IInputMethodManager {
boolean switchToNextInputMethod(in IBinder token, boolean onlyCurrentIme);
boolean shouldOfferSwitchingToNextInputMethod(in IBinder token);
boolean setInputMethodEnabled(String id, boolean enabled);
- oneway void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
+ void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index 4654178..fe1cf72 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -164,8 +164,24 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
+ final ActionMenuView menuParent = (ActionMenuView) parent;
+ final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
+ if (!menuParent.checkLayoutParams(lp)) {
+ actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
+ }
+ return actionView;
+ }
+
+ @Override
+ public void bindItemView(final MenuItemImpl item, MenuView.ItemView itemView) {
+ itemView.initialize(item, 0);
+
+ final ActionMenuView menuView = (ActionMenuView) mMenuView;
+ final ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
+ actionItemView.setItemInvoker(menuView);
+
if (item.hasSubMenu()) {
- actionView.setOnTouchListener(new ForwardingListener(actionView) {
+ actionItemView.setOnTouchListener(new ForwardingListener(actionItemView) {
@Override
public ListPopupWindow getPopup() {
return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null;
@@ -182,24 +198,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
});
} else {
- actionView.setOnTouchListener(null);
+ actionItemView.setOnTouchListener(null);
}
-
- final ActionMenuView menuParent = (ActionMenuView) parent;
- final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
- if (!menuParent.checkLayoutParams(lp)) {
- actionView.setLayoutParams(menuParent.generateLayoutParams(lp));
- }
- return actionView;
- }
-
- @Override
- public void bindItemView(MenuItemImpl item, MenuView.ItemView itemView) {
- itemView.initialize(item, 0);
-
- final ActionMenuView menuView = (ActionMenuView) mMenuView;
- ActionMenuItemView actionItemView = (ActionMenuItemView) itemView;
- actionItemView.setItemInvoker(menuView);
}
@Override
diff --git a/core/java/com/android/internal/view/menu/ListMenuPresenter.java b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
index 4882adc..e1bb3621 100644
--- a/core/java/com/android/internal/view/menu/ListMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ListMenuPresenter.java
@@ -163,7 +163,7 @@ public class ListMenuPresenter implements MenuPresenter, AdapterView.OnItemClick
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
- mMenu.performItemAction(mAdapter.getItem(position), 0);
+ mMenu.performItemAction(mAdapter.getItem(position), this, 0);
}
@Override
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index aff697a..195a00d 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -247,11 +247,17 @@ public class MenuBuilder implements Menu {
startDispatchingItemsChanged();
}
- private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu) {
+ private boolean dispatchSubMenuSelected(SubMenuBuilder subMenu,
+ MenuPresenter preferredPresenter) {
if (mPresenters.isEmpty()) return false;
boolean result = false;
+ // Try the preferred presenter first.
+ if (preferredPresenter != null) {
+ result = preferredPresenter.onSubMenuSelected(subMenu);
+ }
+
for (WeakReference<MenuPresenter> ref : mPresenters) {
final MenuPresenter presenter = ref.get();
if (presenter == null) {
@@ -865,6 +871,10 @@ public class MenuBuilder implements Menu {
}
public boolean performItemAction(MenuItem item, int flags) {
+ return performItemAction(item, null, flags);
+ }
+
+ public boolean performItemAction(MenuItem item, MenuPresenter preferredPresenter, int flags) {
MenuItemImpl itemImpl = (MenuItemImpl) item;
if (itemImpl == null || !itemImpl.isEnabled()) {
@@ -889,7 +899,7 @@ public class MenuBuilder implements Menu {
if (providerHasSubMenu) {
provider.onPrepareSubMenu(subMenu);
}
- invoked |= dispatchSubMenuSelected(subMenu);
+ invoked |= dispatchSubMenuSelected(subMenu, preferredPresenter);
if (!invoked) close(true);
} else {
if ((flags & FLAG_PERFORM_NO_CLOSE) == 0) {