summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk5
-rw-r--r--api/current.txt1
-rw-r--r--core/java/android/app/ActivityManager.java8
-rw-r--r--core/java/android/app/ContextImpl.java2
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java31
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--core/java/android/bluetooth/BluetoothTetheringDataTracker.java5
-rw-r--r--core/java/android/content/res/Configuration.java11
-rwxr-xr-x[-rw-r--r--]core/java/android/database/DefaultDatabaseErrorHandler.java2
-rw-r--r--core/java/android/hardware/location/IFusedLocationHardware.aidl117
-rw-r--r--core/java/android/hardware/location/IFusedLocationHardwareSink.aidl41
-rw-r--r--core/java/android/net/BaseNetworkStateTracker.java5
-rw-r--r--core/java/android/net/CaptivePortalTracker.java44
-rw-r--r--core/java/android/net/ConnectivityManager.java33
-rw-r--r--core/java/android/net/DummyDataStateTracker.java6
-rw-r--r--core/java/android/net/EthernetDataTracker.java5
-rw-r--r--core/java/android/net/IConnectivityManager.aidl4
-rw-r--r--core/java/android/net/MobileDataStateTracker.java12
-rw-r--r--core/java/android/net/NetworkStateTracker.java5
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java3
-rw-r--r--core/java/android/os/BatteryStats.java3
-rw-r--r--core/java/android/os/FileUtils.java86
-rw-r--r--core/java/android/os/Process.java13
-rw-r--r--core/java/android/provider/Settings.java79
-rw-r--r--core/java/android/text/TextUtils.java8
-rw-r--r--core/java/android/view/SurfaceControl.java38
-rw-r--r--core/java/android/view/View.java32
-rw-r--r--core/java/android/widget/AbsListView.java17
-rw-r--r--core/java/android/widget/FastScroller.java101
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/java/com/android/internal/app/PlatLogoActivity.java110
-rw-r--r--core/java/com/android/internal/app/ProcessMap.java (renamed from services/java/com/android/server/ProcessMap.java)2
-rw-r--r--core/java/com/android/internal/app/ProcessStats.java (renamed from services/java/com/android/internal/app/ProcessStats.java)547
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java2
-rw-r--r--core/jni/android/graphics/Canvas.cpp17
-rw-r--r--core/jni/android/graphics/SurfaceTexture.cpp3
-rw-r--r--core/jni/android_net_NetUtils.cpp2
-rw-r--r--core/jni/android_net_wifi_Wifi.cpp66
-rw-r--r--core/jni/android_os_Debug.cpp4
-rw-r--r--core/jni/android_os_FileUtils.cpp42
-rw-r--r--core/jni/android_view_SurfaceControl.cpp8
-rw-r--r--core/res/res/drawable-hdpi/stat_sys_adb_am.pngbin841 -> 1461 bytes
-rw-r--r--core/res/res/drawable-mdpi/stat_sys_adb_am.pngbin511 -> 1102 bytes
-rw-r--r--core/res/res/drawable-nodpi/platlogo.pngbin44507 -> 264785 bytes
-rw-r--r--core/res/res/drawable-nodpi/platlogo_alt.pngbin39313 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/stat_sys_adb_am.pngbin882 -> 1810 bytes
-rw-r--r--core/res/res/values/config.xml2
-rwxr-xr-xcore/res/res/values/symbols.xml1
-rw-r--r--docs/html/guide/topics/providers/content-provider-creating.jd2
-rw-r--r--docs/html/guide/topics/ui/notifiers/notifications.jd2
-rw-r--r--graphics/java/android/graphics/Canvas.java16
-rw-r--r--graphics/java/android/graphics/Paint.java2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp19
-rw-r--r--libs/hwui/OpenGLRenderer.h1
-rw-r--r--location/java/android/location/FusedBatchOptions.aidl19
-rw-r--r--location/java/android/location/FusedBatchOptions.java135
-rw-r--r--location/java/android/location/IFusedGeofenceHardware.aidl93
-rw-r--r--location/java/android/location/IFusedProvider.aidl32
-rw-r--r--location/java/android/location/LocationManager.java11
-rw-r--r--location/lib/java/com/android/location/provider/FusedLocationHardware.java202
-rw-r--r--location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java31
-rw-r--r--location/lib/java/com/android/location/provider/FusedProvider.java59
-rw-r--r--location/lib/java/com/android/location/provider/GmsFusedBatchOptions.java106
-rwxr-xr-x[-rw-r--r--]media/java/android/mtp/MtpDatabase.java2
-rw-r--r--media/mca/filterfw/native/core/gl_env.cpp2
-rw-r--r--media/mca/filterfw/native/core/gl_env.h3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java2
-rw-r--r--packages/SystemUI/AndroidManifest.xml32
-rw-r--r--packages/SystemUI/res/drawable-hdpi/heads_up_window_bg.9.pngbin0 -> 779 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.pngbin0 -> 1222 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/heads_up_window_bg.9.pngbin0 -> 500 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.pngbin0 -> 814 bytes
-rw-r--r--packages/SystemUI/res/drawable-nodpi/qs_coming_soon.pngbin29933 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-nodpi/redbean0.pngbin12835 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-nodpi/redbean1.pngbin15960 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-nodpi/redbean2.pngbin14981 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-nodpi/redbeandroid.pngbin16001 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.pngbin0 -> 1638 bytes
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/BeanBag.java412
-rw-r--r--packages/SystemUI/src/com/android/systemui/BeanBagDream.java47
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java190
-rw-r--r--services/java/com/android/server/AppOpsService.java18
-rw-r--r--services/java/com/android/server/ConnectivityService.java39
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java28
-rw-r--r--services/java/com/android/server/LocationManagerService.java19
-rw-r--r--services/java/com/android/server/accessibility/TouchExplorer.java783
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java34
-rw-r--r--services/java/com/android/server/am/ProcessStatsService.java70
-rw-r--r--services/java/com/android/server/display/DisplayManagerService.java12
-rw-r--r--services/java/com/android/server/display/OverlayDisplayAdapter.java18
-rw-r--r--services/java/com/android/server/display/VirtualDisplayAdapter.java22
-rw-r--r--services/java/com/android/server/display/WifiDisplayAdapter.java15
-rw-r--r--services/java/com/android/server/location/FlpHardwareProvider.java344
-rw-r--r--services/java/com/android/server/location/FusedLocationHardwareSecure.java119
-rw-r--r--services/java/com/android/server/location/FusedProxy.java116
-rw-r--r--services/java/com/android/server/pm/Settings.java19
-rw-r--r--services/jni/Android.mk1
-rw-r--r--services/jni/com_android_server_location_FlpHardwareProvider.cpp901
-rw-r--r--services/jni/onload.cpp2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java8
-rw-r--r--wifi/java/android/net/wifi/WifiMonitor.java506
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java53
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java20
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java5
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pService.java2
107 files changed, 4208 insertions, 1909 deletions
diff --git a/Android.mk b/Android.mk
index 7e34c84..df10876 100644
--- a/Android.mk
+++ b/Android.mk
@@ -128,6 +128,8 @@ LOCAL_SRC_FILES += \
core/java/android/hardware/display/IDisplayManagerCallback.aidl \
core/java/android/hardware/input/IInputManager.aidl \
core/java/android/hardware/input/IInputDevicesChangedListener.aidl \
+ core/java/android/hardware/location/IFusedLocationHardware.aidl \
+ core/java/android/hardware/location/IFusedLocationHardwareSink.aidl \
core/java/android/hardware/location/IGeofenceHardware.aidl \
core/java/android/hardware/location/IGeofenceHardwareCallback.aidl \
core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \
@@ -232,12 +234,14 @@ LOCAL_SRC_FILES += \
keystore/java/android/security/IKeyChainService.aidl \
location/java/android/location/ICountryDetector.aidl \
location/java/android/location/ICountryListener.aidl \
+ location/java/android/location/IFusedProvider.aidl \
location/java/android/location/IGeocodeProvider.aidl \
location/java/android/location/IGeofenceProvider.aidl \
location/java/android/location/IGpsStatusListener.aidl \
location/java/android/location/IGpsStatusProvider.aidl \
location/java/android/location/ILocationListener.aidl \
location/java/android/location/ILocationManager.aidl \
+ location/java/android/location/IFusedGeofenceHardware.aidl \
location/java/android/location/IGpsGeofenceHardware.aidl \
location/java/android/location/INetInitiatedListener.aidl \
location/java/com/android/internal/location/ILocationProvider.aidl \
@@ -379,6 +383,7 @@ aidl_files := \
frameworks/base/location/java/android/location/Geofence.aidl \
frameworks/base/location/java/android/location/Location.aidl \
frameworks/base/location/java/android/location/LocationRequest.aidl \
+ frameworks/base/location/java/android/location/FusedBatchOptions.aidl \
frameworks/base/location/java/com/android/internal/location/ProviderProperties.aidl \
frameworks/base/location/java/com/android/internal/location/ProviderRequest.aidl \
frameworks/base/telephony/java/android/telephony/ServiceState.aidl \
diff --git a/api/current.txt b/api/current.txt
index d79a8c0..b9d51fd 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20716,6 +20716,7 @@ package android.provider {
field public static final java.lang.String ACTION_MEMORY_CARD_SETTINGS = "android.settings.MEMORY_CARD_SETTINGS";
field public static final java.lang.String ACTION_NETWORK_OPERATOR_SETTINGS = "android.settings.NETWORK_OPERATOR_SETTINGS";
field public static final java.lang.String ACTION_NFCSHARING_SETTINGS = "android.settings.NFCSHARING_SETTINGS";
+ field public static final java.lang.String ACTION_NFC_PAYMENT_SETTINGS = "android.settings.NFC_PAYMENT_SETTINGS";
field public static final java.lang.String ACTION_NFC_SETTINGS = "android.settings.NFC_SETTINGS";
field public static final java.lang.String ACTION_PRIVACY_SETTINGS = "android.settings.PRIVACY_SETTINGS";
field public static final java.lang.String ACTION_QUICK_LAUNCH_SETTINGS = "android.settings.QUICK_LAUNCH_SETTINGS";
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 4e6c3dc..c65f17e 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -16,14 +16,13 @@
package android.app;
-import android.R;
import android.os.BatteryStats;
import android.os.IBinder;
import com.android.internal.app.IUsageStats;
+import com.android.internal.app.ProcessStats;
import com.android.internal.os.PkgUsageStats;
import com.android.internal.os.TransferPipe;
import com.android.internal.util.FastPrintWriter;
-import com.android.internal.util.MemInfoReader;
import android.content.ComponentName;
import android.content.Context;
@@ -35,9 +34,7 @@ import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Point;
import android.graphics.Rect;
-import android.hardware.display.DisplayManagerGlobal;
import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
@@ -52,7 +49,6 @@ import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Slog;
-import android.view.Display;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
@@ -2253,7 +2249,7 @@ public class ActivityManager {
PrintWriter pw = new FastPrintWriter(fout);
dumpService(pw, fd, Context.ACTIVITY_SERVICE, new String[] { "package", packageName });
pw.println();
- dumpService(pw, fd, "procstats", new String[] { packageName });
+ dumpService(pw, fd, ProcessStats.SERVICE_NAME, new String[] { packageName });
pw.println();
dumpService(pw, fd, "usagestats", new String[] { "--packages", packageName });
pw.println();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 9faaace..eb5c3e7 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1979,7 +1979,7 @@ class ContextImpl extends Context {
" compatiblity info:" + container.getDisplayMetrics());
}
if (compatInfo == null) {
- compatInfo = CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO;
+ compatInfo = packageInfo.getCompatibilityInfo();
}
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
mDisplayAdjustments.setActivityToken(activityToken);
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 17e8dd9..be831d7 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1527,9 +1527,26 @@ public class DevicePolicyManager {
*/
public boolean setDeviceOwner(String packageName) throws IllegalArgumentException,
IllegalStateException {
+ return setDeviceOwner(packageName, null);
+ }
+
+ /**
+ * @hide
+ * Sets the given package as the device owner. The package must already be installed and there
+ * shouldn't be an existing device owner registered, for this call to succeed. Also, this
+ * method must be called before the device is provisioned.
+ * @param packageName the package name of the application to be registered as the device owner.
+ * @param ownerName the human readable name of the institution that owns this device.
+ * @return whether the package was successfully registered as the device owner.
+ * @throws IllegalArgumentException if the package name is null or invalid
+ * @throws IllegalStateException if a device owner is already registered or the device has
+ * already been provisioned.
+ */
+ public boolean setDeviceOwner(String packageName, String ownerName)
+ throws IllegalArgumentException, IllegalStateException {
if (mService != null) {
try {
- return mService.setDeviceOwner(packageName);
+ return mService.setDeviceOwner(packageName, ownerName);
} catch (RemoteException re) {
Log.w(TAG, "Failed to set device owner");
}
@@ -1581,4 +1598,16 @@ public class DevicePolicyManager {
}
return null;
}
+
+ /** @hide */
+ public String getDeviceOwnerName() {
+ if (mService != null) {
+ try {
+ return mService.getDeviceOwnerName();
+ } catch (RemoteException re) {
+ Log.w(TAG, "Failed to get device owner");
+ }
+ }
+ return null;
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index b2a65bf..9659a91 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -98,7 +98,8 @@ interface IDevicePolicyManager {
void reportFailedPasswordAttempt(int userHandle);
void reportSuccessfulPasswordAttempt(int userHandle);
- boolean setDeviceOwner(String packageName);
+ boolean setDeviceOwner(String packageName, String ownerName);
boolean isDeviceOwner(String packageName);
String getDeviceOwner();
+ String getDeviceOwnerName();
}
diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
index 81c0a6a..0aedecb 100644
--- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
+++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java
@@ -152,6 +152,11 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Re-enable connectivity to a network after a {@link #teardown()}.
*/
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index 6318e38..1c28138 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -786,10 +786,14 @@ public final class Configuration implements Parcelable, Comparable<Configuration
// 2 most significant bits in screenLayout).
setLayoutDirection(locale);
}
+ if (delta.screenLayout != 0 && screenLayout != delta.screenLayout) {
+ changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
+ setLayoutDirection(locale);
+ }
if (delta.userSetLocale && (!userSetLocale || ((changed & ActivityInfo.CONFIG_LOCALE) != 0)))
{
- userSetLocale = true;
changed |= ActivityInfo.CONFIG_LOCALE;
+ userSetLocale = true;
}
if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
&& touchscreen != delta.touchscreen) {
@@ -933,6 +937,9 @@ public final class Configuration implements Parcelable, Comparable<Configuration
changed |= ActivityInfo.CONFIG_LOCALE;
changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
}
+ if (delta.screenLayout != 0 && screenLayout != delta.screenLayout) {
+ changed |= ActivityInfo.CONFIG_LAYOUT_DIRECTION;
+ }
if (delta.touchscreen != TOUCHSCREEN_UNDEFINED
&& touchscreen != delta.touchscreen) {
changed |= ActivityInfo.CONFIG_TOUCHSCREEN;
@@ -1005,7 +1012,7 @@ public final class Configuration implements Parcelable, Comparable<Configuration
public static boolean needNewResources(int configChanges, int interestingChanges) {
return (configChanges & (interestingChanges|ActivityInfo.CONFIG_FONT_SCALE)) != 0;
}
-
+
/**
* @hide Return true if the sequence of 'other' is better than this. Assumes
* that 'this' is your current sequence and 'other' is a new one you have
diff --git a/core/java/android/database/DefaultDatabaseErrorHandler.java b/core/java/android/database/DefaultDatabaseErrorHandler.java
index a9e39c3..b234e34 100644..100755
--- a/core/java/android/database/DefaultDatabaseErrorHandler.java
+++ b/core/java/android/database/DefaultDatabaseErrorHandler.java
@@ -99,7 +99,7 @@ public final class DefaultDatabaseErrorHandler implements DatabaseErrorHandler {
}
Log.e(TAG, "deleting the database file: " + fileName);
try {
- new File(fileName).delete();
+ SQLiteDatabase.deleteDatabase(new File(fileName));
} catch (Exception e) {
/* print warning and ignore exception */
Log.w(TAG, "delete failed: " + e.getMessage());
diff --git a/core/java/android/hardware/location/IFusedLocationHardware.aidl b/core/java/android/hardware/location/IFusedLocationHardware.aidl
new file mode 100644
index 0000000..382c12c
--- /dev/null
+++ b/core/java/android/hardware/location/IFusedLocationHardware.aidl
@@ -0,0 +1,117 @@
+/*
+ * 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/license/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.hardware.location;
+
+import android.hardware.location.IFusedLocationHardwareSink;
+import android.location.FusedBatchOptions;
+
+/**
+ * Fused Location hardware interface.
+ * This interface is the basic set of supported functionality by Fused Hardware
+ * modules that offer Location batching capabilities.
+ *
+ * @hide
+ */
+interface IFusedLocationHardware {
+ /**
+ * Registers a sink with the Location Hardware object.
+ *
+ * @param eventSink The sink to register.
+ */
+ void registerSink(in IFusedLocationHardwareSink eventSink);
+
+ /**
+ * Unregisters a sink with the Location Hardware object.
+ *
+ * @param eventSink The sink to unregister.
+ */
+ void unregisterSink(in IFusedLocationHardwareSink eventSink);
+
+ /**
+ * Provides access to the batch size available in Hardware.
+ *
+ * @return The batch size the hardware supports.
+ */
+ int getSupportedBatchSize();
+
+ /**
+ * Requests the Hardware to start batching locations.
+ *
+ * @param id An Id associated with the request.
+ * @param batchOptions The options required for batching.
+ *
+ * @throws RuntimeException if the request Id exists.
+ */
+ void startBatching(in int id, in FusedBatchOptions batchOptions);
+
+ /**
+ * Requests the Hardware to stop batching for the given Id.
+ *
+ * @param id The request that needs to be stopped.
+ * @throws RuntimeException if the request Id is unknown.
+ */
+ void stopBatching(in int id);
+
+ /**
+ * Updates a batching operation in progress.
+ *
+ * @param id The Id of the operation to update.
+ * @param batchOptions The options to apply to the given operation.
+ *
+ * @throws RuntimeException if the Id of the request is unknown.
+ */
+ void updateBatchingOptions(in int id, in FusedBatchOptions batchOptions);
+
+ /**
+ * Requests the most recent locations available in Hardware.
+ * This operation does not dequeue the locations, so still other batching
+ * events will continue working.
+ *
+ * @param batchSizeRequested The number of locations requested.
+ */
+ void requestBatchOfLocations(in int batchSizeRequested);
+
+ /**
+ * Flags if the Hardware supports injection of diagnostic data.
+ *
+ * @return True if data injection is supported, false otherwise.
+ */
+ boolean supportsDiagnosticDataInjection();
+
+ /**
+ * Injects diagnostic data into the Hardware subsystem.
+ *
+ * @param data The data to inject.
+ * @throws RuntimeException if injection is not supported.
+ */
+ void injectDiagnosticData(in String data);
+
+ /**
+ * Flags if the Hardware supports injection of device context information.
+ *
+ * @return True if device context injection is supported, false otherwise.
+ */
+ boolean supportsDeviceContextInjection();
+
+ /**
+ * Injects device context information into the Hardware subsystem.
+ *
+ * @param deviceEnabledContext The context to inject.
+ * @throws RuntimeException if injection is not supported.
+ */
+ void injectDeviceContext(in int deviceEnabledContext);
+}
diff --git a/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
new file mode 100644
index 0000000..a11d8ab
--- /dev/null
+++ b/core/java/android/hardware/location/IFusedLocationHardwareSink.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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/license/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.hardware.location;
+
+import android.location.Location;
+
+/**
+ * Fused Location hardware event sink interface.
+ * This interface defines the set of events that the FusedLocationHardware provides.
+ *
+ * @hide
+ */
+interface IFusedLocationHardwareSink {
+ /**
+ * Event generated when a batch of location information is available.
+ *
+ * @param locations The batch of location information available.
+ */
+ void onLocationAvailable(in Location[] locations);
+
+ /**
+ * Event generated from FLP HAL to provide diagnostic data to the platform.
+ *
+ * @param data The diagnostic data provided by FLP HAL.
+ */
+ void onDiagnosticDataAvailable(in String data);
+} \ No newline at end of file
diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java
index 1165281..e87f84c 100644
--- a/core/java/android/net/BaseNetworkStateTracker.java
+++ b/core/java/android/net/BaseNetworkStateTracker.java
@@ -102,6 +102,11 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker {
}
@Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
+ @Override
public boolean setRadio(boolean turnOn) {
// Base tracker doesn't handle radios
return true;
diff --git a/core/java/android/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
index 19d74ed..74c2c59 100644
--- a/core/java/android/net/CaptivePortalTracker.java
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -46,6 +46,7 @@ import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellInfoWcdma;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
@@ -54,6 +55,7 @@ import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.Inet4Address;
+import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.List;
@@ -65,7 +67,7 @@ import com.android.internal.R;
* @hide
*/
public class CaptivePortalTracker extends StateMachine {
- private static final boolean DBG = false;
+ private static final boolean DBG = true;
private static final String TAG = "CaptivePortalTracker";
private static final String DEFAULT_SERVER = "clients3.google.com";
@@ -301,6 +303,7 @@ public class CaptivePortalTracker extends StateMachine {
} else {
if (DBG) log("Not captive network " + mNetworkInfo);
}
+ notifyPortalCheckCompleted(mNetworkInfo, captive);
if (mDeviceProvisioned) {
if (captive) {
// Setup Wizard will assist the user in connecting to a captive
@@ -331,12 +334,26 @@ public class CaptivePortalTracker extends StateMachine {
return;
}
try {
+ if (DBG) log("notifyPortalCheckComplete: ni=" + info);
mConnService.captivePortalCheckComplete(info);
} catch(RemoteException e) {
e.printStackTrace();
}
}
+ private void notifyPortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
+ if (info == null) {
+ loge("notifyPortalCheckComplete on null");
+ return;
+ }
+ try {
+ if (DBG) log("notifyPortalCheckCompleted: captive=" + isCaptivePortal + " ni=" + info);
+ mConnService.captivePortalCheckCompleted(info, isCaptivePortal);
+ } catch(RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
private boolean isActiveNetwork(NetworkInfo info) {
try {
NetworkInfo active = mConnService.getActiveNetworkInfo();
@@ -382,6 +399,12 @@ public class CaptivePortalTracker extends StateMachine {
sendNetworkConditionsBroadcast(true /* response received */, isCaptivePortal,
requestTimestamp, responseTimestamp);
return isCaptivePortal;
+ } catch (SocketTimeoutException e) {
+ if (DBG) log("Probably a portal: exception " + e);
+ if (requestTimestamp != -1) {
+ sendFailedCaptivePortalCheckBroadcast(requestTimestamp);
+ } // else something went wrong with setting up the urlConnection
+ return true;
} catch (IOException e) {
if (DBG) log("Probably not a portal: exception " + e);
if (requestTimestamp != -1) {
@@ -415,6 +438,7 @@ public class CaptivePortalTracker extends StateMachine {
private void setNotificationVisible(boolean visible) {
// if it should be hidden and it is already hidden, then noop
if (!visible && !mNotificationShown) {
+ if (DBG) log("setNotivicationVisible: false and not shown, so noop");
return;
}
@@ -426,12 +450,14 @@ public class CaptivePortalTracker extends StateMachine {
CharSequence title;
CharSequence details;
int icon;
+ String url = null;
switch (mNetworkInfo.getType()) {
case ConnectivityManager.TYPE_WIFI:
title = r.getString(R.string.wifi_available_sign_in, 0);
details = r.getString(R.string.network_available_sign_in_detailed,
mNetworkInfo.getExtraInfo());
icon = R.drawable.stat_notify_wifi_in_range;
+ url = mUrl;
break;
case ConnectivityManager.TYPE_MOBILE:
title = r.getString(R.string.network_available_sign_in, 0);
@@ -439,12 +465,24 @@ public class CaptivePortalTracker extends StateMachine {
// name has been added to it
details = mTelephonyManager.getNetworkOperatorName();
icon = R.drawable.stat_notify_rssi_in_range;
+ try {
+ url = mConnService.getMobileProvisioningUrl();
+ if (TextUtils.isEmpty(url)) {
+ url = mConnService.getMobileRedirectedProvisioningUrl();
+ }
+ } catch(RemoteException e) {
+ e.printStackTrace();
+ }
+ if (TextUtils.isEmpty(url)) {
+ url = mUrl;
+ }
break;
default:
title = r.getString(R.string.network_available_sign_in, 0);
details = r.getString(R.string.network_available_sign_in_detailed,
mNetworkInfo.getExtraInfo());
icon = R.drawable.stat_notify_rssi_in_range;
+ url = mUrl;
break;
}
@@ -452,15 +490,17 @@ public class CaptivePortalTracker extends StateMachine {
notification.when = 0;
notification.icon = icon;
notification.flags = Notification.FLAG_AUTO_CANCEL;
- Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(mUrl));
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
intent.setFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT |
Intent.FLAG_ACTIVITY_NEW_TASK);
notification.contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
notification.tickerText = title;
notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
+ if (DBG) log("setNotivicationVisible: make visible");
notificationManager.notify(NOTIFICATION_ID, 1, notification);
} else {
+ if (DBG) log("setNotivicationVisible: cancel notification");
notificationManager.cancel(NOTIFICATION_ID, 1);
}
mNotificationShown = visible;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 1dbe34e..1b418fa 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1324,6 +1324,25 @@ public class ConnectivityManager {
}
/**
+ * Signal that the captive portal check on the indicated network
+ * is complete and whether its a captive portal or not.
+ *
+ * @param info the {@link NetworkInfo} object for the networkType
+ * in question.
+ * @param isCaptivePortal true/false.
+ *
+ * <p>This method requires the call to hold the permission
+ * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
+ * {@hide}
+ */
+ public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
+ try {
+ mService.captivePortalCheckCompleted(info, isCaptivePortal);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Supply the backend messenger for a network tracker
*
* @param type NetworkType to set
@@ -1401,7 +1420,7 @@ public class ConnectivityManager {
}
/**
- * Get the carrier provisioning url.
+ * Get the mobile provisioning url.
* {@hide}
*/
public String getMobileProvisioningUrl() {
@@ -1411,4 +1430,16 @@ public class ConnectivityManager {
}
return null;
}
+
+ /**
+ * Get the mobile redirected provisioning url.
+ * {@hide}
+ */
+ public String getMobileRedirectedProvisioningUrl() {
+ try {
+ return mService.getMobileRedirectedProvisioningUrl();
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
}
diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java
index 15a81f3..ee738fd 100644
--- a/core/java/android/net/DummyDataStateTracker.java
+++ b/core/java/android/net/DummyDataStateTracker.java
@@ -120,10 +120,16 @@ public class DummyDataStateTracker implements NetworkStateTracker {
return true;
}
+ @Override
public void captivePortalCheckComplete() {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Record the detailed state of a network, and if it is a
* change from the previous state, send a notification to
diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java
index 7b803a8..7999c66 100644
--- a/core/java/android/net/EthernetDataTracker.java
+++ b/core/java/android/net/EthernetDataTracker.java
@@ -280,6 +280,11 @@ public class EthernetDataTracker implements NetworkStateTracker {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index b0f7fc6..992ec37 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -134,6 +134,8 @@ interface IConnectivityManager
void captivePortalCheckComplete(in NetworkInfo info);
+ void captivePortalCheckCompleted(in NetworkInfo info, boolean isCaptivePortal);
+
void supplyMessenger(int networkType, in Messenger messenger);
int findConnectionTypeForIface(in String iface);
@@ -141,4 +143,6 @@ interface IConnectivityManager
int checkMobileProvisioning(boolean sendNotification, int suggestedTimeOutMs, in ResultReceiver resultReceiver);
String getMobileProvisioningUrl();
+
+ String getMobileRedirectedProvisioningUrl();
}
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 54273ee..e4fd312 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -40,6 +40,7 @@ import com.android.internal.util.AsyncChannel;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* Track the state of mobile data connectivity. This is done by
@@ -75,6 +76,8 @@ public class MobileDataStateTracker implements NetworkStateTracker {
private Handler mHandler;
private AsyncChannel mDataConnectionTrackerAc;
+ private AtomicBoolean mIsCaptivePortal = new AtomicBoolean(false);
+
/**
* Create a new MobileDataStateTracker
* @param netType the ConnectivityManager network type
@@ -377,6 +380,15 @@ public class MobileDataStateTracker implements NetworkStateTracker {
// not implemented
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ if (mIsCaptivePortal.getAndSet(isCaptivePortal) != isCaptivePortal) {
+ // Captive portal change enable/disable failing fast
+ setEnableFailFastMobileData(
+ isCaptivePortal ? DctConstants.ENABLED : DctConstants.DISABLED);
+ }
+ }
+
/**
* Record the detailed state of a network, and if it is a
* change from the previous state, send a notification to
diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java
index cf77a1c..9ed7533 100644
--- a/core/java/android/net/NetworkStateTracker.java
+++ b/core/java/android/net/NetworkStateTracker.java
@@ -144,6 +144,11 @@ public interface NetworkStateTracker {
public void captivePortalCheckComplete();
/**
+ * Captive portal check has completed
+ */
+ public void captivePortalCheckCompleted(boolean isCaptive);
+
+ /**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}
*/
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index ffa7d7e..3f7e3ef 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -188,7 +188,8 @@ public final class ApduServiceInfo implements Parcelable {
currentGroup != null) {
final TypedArray a = res.obtainAttributes(attrs,
com.android.internal.R.styleable.AidFilter);
- String aid = a.getString(com.android.internal.R.styleable.AidFilter_name);
+ String aid = a.getString(com.android.internal.R.styleable.AidFilter_name).
+ toUpperCase();
if (isValidAid(aid) && !currentGroup.aids.contains(aid)) {
currentGroup.aids.add(aid);
mAids.add(aid);
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 12646bd..38ffb96 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -155,6 +155,7 @@ public abstract class BatteryStats implements Parcelable {
private static final String BATTERY_LEVEL_DATA = "lv";
private static final String WIFI_DATA = "wfl";
private static final String MISC_DATA = "m";
+ private static final String HISTORY_DATA = "h";
private static final String SCREEN_BRIGHTNESS_DATA = "br";
private static final String SIGNAL_STRENGTH_TIME_DATA = "sgt";
private static final String SIGNAL_SCANNING_TIME_DATA = "sst";
@@ -2390,7 +2391,7 @@ public abstract class BatteryStats implements Parcelable {
while (getNextHistoryLocked(rec)) {
pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
pw.print(0); pw.print(',');
- pw.print("h"); pw.print(',');
+ pw.print(HISTORY_DATA); pw.print(',');
hprinter.printNextItemCheckin(pw, rec, now);
pw.println();
}
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 97ea99d..4d48fd4 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -17,10 +17,17 @@
package android.os;
import android.util.Log;
+import android.util.Slog;
+
+import libcore.io.ErrnoException;
+import libcore.io.IoUtils;
+import libcore.io.Libcore;
+import libcore.io.OsConstants;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -58,9 +65,84 @@ public class FileUtils {
/** Regular expression for safe filenames: no spaces or metacharacters */
private static final Pattern SAFE_FILENAME_PATTERN = Pattern.compile("[\\w%+,./=_-]+");
- public static native int setPermissions(String file, int mode, int uid, int gid);
+ /**
+ * Set owner and mode of of given {@link File}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(File path, int mode, int uid, int gid) {
+ return setPermissions(path.getAbsolutePath(), mode, uid, gid);
+ }
+
+ /**
+ * Set owner and mode of of given path.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(String path, int mode, int uid, int gid) {
+ try {
+ Libcore.os.chmod(path, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chmod(" + path + "): " + e);
+ return e.errno;
+ }
+
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.chown(path, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to chown(" + path + "): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Set owner and mode of of given {@link FileDescriptor}.
+ *
+ * @param mode to apply through {@code chmod}
+ * @param uid to apply through {@code chown}, or -1 to leave unchanged
+ * @param gid to apply through {@code chown}, or -1 to leave unchanged
+ * @return 0 on success, otherwise errno.
+ */
+ public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) {
+ try {
+ Libcore.os.fchmod(fd, mode);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchmod(): " + e);
+ return e.errno;
+ }
- public static native int getUid(String file);
+ if (uid >= 0 || gid >= 0) {
+ try {
+ Libcore.os.fchown(fd, uid, gid);
+ } catch (ErrnoException e) {
+ Slog.w(TAG, "Failed to fchown(): " + e);
+ return e.errno;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Return owning UID of given path, otherwise -1.
+ */
+ public static int getUid(String path) {
+ try {
+ return Libcore.os.stat(path).st_uid;
+ } catch (ErrnoException e) {
+ return -1;
+ }
+ }
/** returns the FAT file system volume ID for the volume mounted
* at the given mount point, or -1 for failure
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index ab0543d..cf9ddb3 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -100,12 +100,6 @@ public class Process {
public static final int DRM_UID = 1019;
/**
- * Defines the GID for the group that allows write access to the SD card.
- * @hide
- */
- public static final int SDCARD_RW_GID = 1015;
-
- /**
* Defines the UID/GID for the group that controls VPN services.
* @hide
*/
@@ -130,11 +124,18 @@ public class Process {
public static final int MEDIA_RW_GID = 1023;
/**
+ * Access to installed package details
+ * @hide
+ */
+ public static final int PACKAGE_INFO_GID = 1032;
+
+ /**
* Defines the start of a range of UIDs (and GIDs), going from this
* number to {@link #LAST_APPLICATION_UID} that are reserved for assigning
* to applications.
*/
public static final int FIRST_APPLICATION_UID = 10000;
+
/**
* Last of application-specific UIDs starting at
* {@link #FIRST_APPLICATION_UID}.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 130123f..585115a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -33,6 +33,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.SQLException;
+import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.net.wifi.WifiManager;
@@ -643,6 +644,23 @@ public final class Settings {
"android.settings.NFCSHARING_SETTINGS";
/**
+ * Activity Action: Show NFC Tap & Pay settings
+ * <p>
+ * This shows UI that allows the user to configure Tap&Pay
+ * settings.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NFC_PAYMENT_SETTINGS =
+ "android.settings.NFC_PAYMENT_SETTINGS";
+
+ /**
* Activity Action: Show Daydream settings.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -737,6 +755,10 @@ public final class Settings {
private static final String TAG = "Settings";
private static final boolean LOCAL_LOGV = false;
+ // Lock ensures that when enabling/disabling the master location switch, we don't end up
+ // with a partial enable/disable state in multi-threaded situations.
+ private static final Object mLocationSettingsLock = new Object();
+
public static class SettingNotFoundException extends AndroidException {
public SettingNotFoundException(String msg) {
super(msg);
@@ -4303,6 +4325,20 @@ public final class Settings {
}
/**
+ * Helper method for determining if the location master switch is enabled.
+ * @param cr the content resolver to use
+ * @return true if the master switch is enabled
+ * @hide
+ */
+ public static final boolean isLocationMasterSwitchEnabled(ContentResolver cr) {
+ int uid = UserHandle.myUserId();
+ synchronized (mLocationSettingsLock) {
+ return isLocationProviderEnabledForUser(cr, LocationManager.NETWORK_PROVIDER, uid)
+ || isLocationProviderEnabledForUser(cr, LocationManager.GPS_PROVIDER, uid);
+ }
+ }
+
+ /**
* Helper method for determining if a location provider is enabled.
* @param cr the content resolver to use
* @param provider the location provider to query
@@ -4328,6 +4364,23 @@ public final class Settings {
}
/**
+ * Thread-safe method for enabling or disabling the location master switch.
+ *
+ * @param cr the content resolver to use
+ * @param enabled true if master switch should be enabled
+ * @hide
+ */
+ public static final void setLocationMasterSwitchEnabled(ContentResolver cr,
+ boolean enabled) {
+ int uid = UserHandle.myUserId();
+ synchronized (mLocationSettingsLock) {
+ setLocationProviderEnabledForUser(cr, LocationManager.GPS_PROVIDER, enabled, uid);
+ setLocationProviderEnabledForUser(cr, LocationManager.NETWORK_PROVIDER, enabled,
+ uid);
+ }
+ }
+
+ /**
* Thread-safe method for enabling or disabling a single location provider.
* @param cr the content resolver to use
* @param provider the location provider to enable or disable
@@ -4337,16 +4390,18 @@ public final class Settings {
*/
public static final void setLocationProviderEnabledForUser(ContentResolver cr,
String provider, boolean enabled, int userId) {
- // to ensure thread safety, we write the provider name with a '+' or '-'
- // and let the SettingsProvider handle it rather than reading and modifying
- // the list of enabled providers.
- if (enabled) {
- provider = "+" + provider;
- } else {
- provider = "-" + provider;
+ synchronized (mLocationSettingsLock) {
+ // to ensure thread safety, we write the provider name with a '+' or '-'
+ // and let the SettingsProvider handle it rather than reading and modifying
+ // the list of enabled providers.
+ if (enabled) {
+ provider = "+" + provider;
+ } else {
+ provider = "-" + provider;
+ }
+ putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
+ userId);
}
- putStringForUser(cr, Settings.Secure.LOCATION_PROVIDERS_ALLOWED, provider,
- userId);
}
}
@@ -5624,6 +5679,12 @@ public final class Settings {
public static final String SELINUX_STATUS = "selinux_status";
/**
+ * Developer setting to force RTL layout.
+ * @hide
+ */
+ public static final String DEVELOPMENT_FORCE_RTL = "debug.force_rtl";
+
+ /**
* Settings to backup. This is here so that it's in the same place as the settings
* keys and easy to update.
*
diff --git a/core/java/android/text/TextUtils.java b/core/java/android/text/TextUtils.java
index e2035c2..596ca8c 100644
--- a/core/java/android/text/TextUtils.java
+++ b/core/java/android/text/TextUtils.java
@@ -19,6 +19,8 @@ package android.text;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SystemProperties;
+import android.provider.Settings;
import android.text.style.AbsoluteSizeSpan;
import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan;
@@ -1743,8 +1745,10 @@ public class TextUtils {
return View.LAYOUT_DIRECTION_RTL;
}
}
-
- return View.LAYOUT_DIRECTION_LTR;
+ // If forcing into RTL layout mode, return RTL as default, else LTR
+ return SystemProperties.getBoolean(Settings.Global.DEVELOPMENT_FORCE_RTL, false)
+ ? View.LAYOUT_DIRECTION_RTL
+ : View.LAYOUT_DIRECTION_LTR;
}
/**
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 6b530ef..dc31e0b 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -59,13 +59,14 @@ public class SurfaceControl {
private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
private static native IBinder nativeCreateDisplay(String name, boolean secure);
+ private static native void nativeDestroyDisplay(IBinder displayToken);
private static native void nativeSetDisplaySurface(
IBinder displayToken, int nativeSurfaceObject);
private static native void nativeSetDisplayLayerStack(
IBinder displayToken, int layerStack);
private static native void nativeSetDisplayProjection(
IBinder displayToken, int orientation,
- int l, int t, int r, int b,
+ int l, int t, int r, int b,
int L, int T, int R, int B);
private static native boolean nativeGetDisplayInfo(
IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
@@ -103,7 +104,7 @@ public class SurfaceControl {
* measures will be taken to disallow the surface's content to be copied
* from another process. In particular, screenshots and VNC servers will
* be disabled, but other measures can take place, for instance the
- * surface might not be hardware accelerated.
+ * surface might not be hardware accelerated.
*
*/
public static final int SECURE = 0x00000080;
@@ -247,10 +248,10 @@ public class SurfaceControl {
throw new OutOfResourcesException(
"Couldn't allocate SurfaceControl native object");
}
-
+
mCloseGuard.open("release");
}
-
+
@Override
protected void finalize() throws Throwable {
try {
@@ -300,7 +301,7 @@ public class SurfaceControl {
if (mNativeObject == 0) throw new NullPointerException(
"mNativeObject is null. Have you called release() already?");
}
-
+
/*
* set surface parameters.
* needs to be inside open/closeTransaction block
@@ -369,7 +370,7 @@ public class SurfaceControl {
public void setWindowCrop(Rect crop) {
checkNotReleased();
if (crop != null) {
- nativeSetWindowCrop(mNativeObject,
+ nativeSetWindowCrop(mNativeObject,
crop.left, crop.top, crop.right, crop.bottom);
} else {
nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0);
@@ -397,19 +398,19 @@ public class SurfaceControl {
public float xDpi;
public float yDpi;
public boolean secure;
-
+
public PhysicalDisplayInfo() {
}
-
+
public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
copyFrom(other);
}
-
+
@Override
public boolean equals(Object o) {
return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
}
-
+
public boolean equals(PhysicalDisplayInfo other) {
return other != null
&& width == other.width
@@ -420,12 +421,12 @@ public class SurfaceControl {
&& yDpi == other.yDpi
&& secure == other.secure;
}
-
+
@Override
public int hashCode() {
return 0; // don't care
}
-
+
public void copyFrom(PhysicalDisplayInfo other) {
width = other.width;
height = other.height;
@@ -435,7 +436,7 @@ public class SurfaceControl {
yDpi = other.yDpi;
secure = other.secure;
}
-
+
// For debugging purposes
@Override
public String toString() {
@@ -481,7 +482,7 @@ public class SurfaceControl {
throw new IllegalArgumentException("displayRect must not be null");
}
nativeSetDisplayProjection(displayToken, orientation,
- layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
+ layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
}
@@ -513,6 +514,13 @@ public class SurfaceControl {
return nativeCreateDisplay(name, secure);
}
+ public static void destroyDisplay(IBinder displayToken) {
+ if (displayToken == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+ nativeDestroyDisplay(displayToken);
+ }
+
public static IBinder getBuiltInDisplay(int builtInDisplayId) {
return nativeGetBuiltInDisplay(builtInDisplayId);
}
@@ -608,7 +616,7 @@ public class SurfaceControl {
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
return nativeScreenshot(displayToken, width, height, 0, 0, true);
}
-
+
private static void screenshot(IBinder display, Surface consumer,
int width, int height, int minLayer, int maxLayer, boolean allLayers) {
if (display == null) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 20938f5..3dff1b0 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12062,7 +12062,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Resolve padding depending on layout direction.
+ * Resolves padding depending on layout direction, if applicable, and
+ * recomputes internal padding values to adjust for scroll bars.
*
* @hide
*/
@@ -12102,11 +12103,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
- internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
- mUserPaddingBottom);
onRtlPropertiesChanged(resolvedLayoutDirection);
}
+ internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
+
mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
}
@@ -14659,13 +14660,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide
*/
protected void resolveDrawables() {
- if (canResolveLayoutDirection()) {
- if (mBackground != null) {
- mBackground.setLayoutDirection(getLayoutDirection());
- }
- mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
- onResolveDrawables(getLayoutDirection());
+ // Drawables resolution may need to happen before resolving the layout direction (which is
+ // done only during the measure() call).
+ // If the layout direction is not resolved yet, we cannot resolve the Drawables except in
+ // one case: when the raw layout direction has not been defined as LAYOUT_DIRECTION_INHERIT.
+ // So, if the raw layout direction is LAYOUT_DIRECTION_LTR or LAYOUT_DIRECTION_RTL or
+ // LAYOUT_DIRECTION_LOCALE, we can "cheat" and we don't need to wait for the layout
+ // direction to be resolved as its resolved value will be the same as its raw value.
+ if (!isLayoutDirectionResolved() &&
+ getRawLayoutDirection() == View.LAYOUT_DIRECTION_INHERIT) {
+ return;
+ }
+
+ final int layoutDirection = isLayoutDirectionResolved() ?
+ getLayoutDirection() : getRawLayoutDirection();
+
+ if (mBackground != null) {
+ mBackground.setLayoutDirection(layoutDirection);
}
+ mPrivateFlags2 |= PFLAG2_DRAWABLE_RESOLVED;
+ onResolveDrawables(layoutDirection);
}
/**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3f391ad..0ed846b 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1243,6 +1243,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mFastScroller = new FastScroller(this);
mFastScroller.setEnabled(true);
}
+
+ recomputePadding();
+
+ if (mFastScroller != null) {
+ mFastScroller.updateLayout();
+ }
}
/**
@@ -1303,7 +1309,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@Override
public int getVerticalScrollbarWidth() {
- if (isFastScrollAlwaysVisible() && mFastScroller != null) {
+ if (mFastScroller != null && mFastScroller.isEnabled()) {
return Math.max(super.getVerticalScrollbarWidth(), mFastScroller.getWidth());
}
return super.getVerticalScrollbarWidth();
@@ -1327,6 +1333,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
+ @Override
+ public void setScrollBarStyle(int style) {
+ super.setScrollBarStyle(style);
+ if (mFastScroller != null) {
+ mFastScroller.setScrollBarStyle(style);
+ }
+ }
+
/**
* If fast scroll is enabled, then don't draw the vertical scrollbar.
* @hide
@@ -2787,7 +2801,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@Override
public void onRtlPropertiesChanged(int layoutDirection) {
super.onRtlPropertiesChanged(layoutDirection);
-
if (mFastScroller != null) {
mFastScroller.setScrollbarPosition(getVerticalScrollbarPosition());
}
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index 393720f..c48955f 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -131,6 +131,9 @@ class FastScroller {
/** Whether there is a track image to display. */
private final boolean mHasTrackImage;
+ /** Total width of decorations. */
+ private final int mWidth;
+
/** Set containing decoration transition animations. */
private AnimatorSet mDecorAnimation;
@@ -155,6 +158,9 @@ class FastScroller {
/** The index of the current section. */
private int mCurrentSection = -1;
+ /** The current scrollbar position. */
+ private int mScrollbarPosition = -1;
+
/** Whether the list is long enough to need a fast scroller. */
private boolean mLongList;
@@ -194,6 +200,9 @@ class FastScroller {
*/
private int mOverlayPosition;
+ /** Current scrollbar style, including inset and overlay properties. */
+ private int mScrollBarStyle;
+
/** Whether to precisely match the thumb position to the list. */
private boolean mMatchDragPosition;
@@ -245,34 +254,44 @@ class FastScroller {
final Resources res = context.getResources();
final TypedArray ta = context.getTheme().obtainStyledAttributes(ATTRS);
- mTrackImage = new ImageView(context);
+ final ImageView trackImage = new ImageView(context);
+ mTrackImage = trackImage;
+
+ int width = 0;
// Add track to overlay if it has an image.
- final int trackResId = ta.getResourceId(TRACK_DRAWABLE, 0);
- if (trackResId != 0) {
+ final Drawable trackDrawable = ta.getDrawable(TRACK_DRAWABLE);
+ if (trackDrawable != null) {
mHasTrackImage = true;
- mTrackImage.setBackgroundResource(trackResId);
- mOverlay.add(mTrackImage);
+ trackImage.setBackground(trackDrawable);
+ mOverlay.add(trackImage);
+ width = Math.max(width, trackDrawable.getIntrinsicWidth());
} else {
mHasTrackImage = false;
}
- mThumbImage = new ImageView(context);
+ final ImageView thumbImage = new ImageView(context);
+ mThumbImage = thumbImage;
// Add thumb to overlay if it has an image.
final Drawable thumbDrawable = ta.getDrawable(THUMB_DRAWABLE);
if (thumbDrawable != null) {
- mThumbImage.setImageDrawable(thumbDrawable);
- mOverlay.add(mThumbImage);
+ thumbImage.setImageDrawable(thumbDrawable);
+ mOverlay.add(thumbImage);
+ width = Math.max(width, thumbDrawable.getIntrinsicWidth());
}
// If necessary, apply minimum thumb width and height.
if (thumbDrawable.getIntrinsicWidth() <= 0 || thumbDrawable.getIntrinsicHeight() <= 0) {
- mThumbImage.setMinimumWidth(res.getDimensionPixelSize(R.dimen.fastscroll_thumb_width));
- mThumbImage.setMinimumHeight(
+ final int minWidth = res.getDimensionPixelSize(R.dimen.fastscroll_thumb_width);
+ thumbImage.setMinimumWidth(minWidth);
+ thumbImage.setMinimumHeight(
res.getDimensionPixelSize(R.dimen.fastscroll_thumb_height));
+ width = Math.max(width, minWidth);
}
+ mWidth = width;
+
final int previewSize = res.getDimensionPixelSize(R.dimen.fastscroll_overlay_size);
mPreviewImage = new ImageView(context);
mPreviewImage.setMinimumWidth(previewSize);
@@ -297,10 +316,11 @@ class FastScroller {
mOverlayPosition = ta.getInt(OVERLAY_POSITION, OVERLAY_FLOATING);
ta.recycle();
+ mScrollBarStyle = listView.getScrollBarStyle();
mScrollCompleted = true;
mState = STATE_VISIBLE;
- mMatchDragPosition =
- context.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB;
+ mMatchDragPosition = context.getApplicationInfo().targetSdkVersion
+ >= Build.VERSION_CODES.HONEYCOMB;
getSectionsFromIndexer();
refreshDrawablePressedState();
@@ -362,6 +382,14 @@ class FastScroller {
return mAlwaysShow;
}
+ public void setScrollBarStyle(int style) {
+ if (mScrollBarStyle != style) {
+ mScrollBarStyle = style;
+
+ updateLayout();
+ }
+ }
+
/**
* Immediately transitions the fast scroller decorations to a hidden state.
*/
@@ -375,25 +403,29 @@ class FastScroller {
View.SCROLLBAR_POSITION_LEFT : View.SCROLLBAR_POSITION_RIGHT;
}
- mLayoutFromRight = position != View.SCROLLBAR_POSITION_LEFT;
+ if (mScrollbarPosition != position) {
+ mScrollbarPosition = position;
+ mLayoutFromRight = position != View.SCROLLBAR_POSITION_LEFT;
- final int previewResId = mPreviewResId[mLayoutFromRight ? PREVIEW_RIGHT : PREVIEW_LEFT];
- mPreviewImage.setBackgroundResource(previewResId);
+ final int previewResId = mPreviewResId[mLayoutFromRight ? PREVIEW_RIGHT : PREVIEW_LEFT];
+ mPreviewImage.setBackgroundResource(previewResId);
- // Add extra padding for text.
- final Drawable background = mPreviewImage.getBackground();
- if (background != null) {
- final Rect padding = mTempBounds;
- background.getPadding(padding);
- padding.offset(mPreviewPadding, mPreviewPadding);
- mPreviewImage.setPadding(padding.left, padding.top, padding.right, padding.bottom);
- }
+ // Add extra padding for text.
+ final Drawable background = mPreviewImage.getBackground();
+ if (background != null) {
+ final Rect padding = mTempBounds;
+ background.getPadding(padding);
+ padding.offset(mPreviewPadding, mPreviewPadding);
+ mPreviewImage.setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ }
- updateLayout();
+ // Requires re-layout.
+ updateLayout();
+ }
}
public int getWidth() {
- return mThumbImage.getWidth();
+ return mWidth;
}
public void onSizeChanged(int w, int h, int oldw, int oldh) {
@@ -437,7 +469,7 @@ class FastScroller {
/**
* Measures and layouts the scrollbar and decorations.
*/
- private void updateLayout() {
+ public void updateLayout() {
// Prevent re-entry when RTL properties change as a side-effect of
// resolving padding.
if (mUpdatingLayout) {
@@ -594,21 +626,36 @@ class FastScroller {
out.set(left, top, right, bottom);
}
+ /**
+ * Updates the container rectangle used for layout.
+ */
private void updateContainerRect() {
final AbsListView list = mList;
+ list.resolvePadding();
+
final Rect container = mContainerRect;
container.left = 0;
container.top = 0;
container.right = list.getWidth();
container.bottom = list.getHeight();
- final int scrollbarStyle = list.getScrollBarStyle();
+ final int scrollbarStyle = mScrollBarStyle;
if (scrollbarStyle == View.SCROLLBARS_INSIDE_INSET
|| scrollbarStyle == View.SCROLLBARS_INSIDE_OVERLAY) {
container.left += list.getPaddingLeft();
container.top += list.getPaddingTop();
container.right -= list.getPaddingRight();
container.bottom -= list.getPaddingBottom();
+
+ // In inset mode, we need to adjust for padded scrollbar width.
+ if (scrollbarStyle == View.SCROLLBARS_INSIDE_INSET) {
+ final int width = getWidth();
+ if (mScrollbarPosition == View.SCROLLBAR_POSITION_RIGHT) {
+ container.right += width;
+ } else {
+ container.left -= width;
+ }
+ }
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3181164..9c21f0d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1378,6 +1378,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
} else {
dr.mDrawableSizeEnd = dr.mDrawableHeightEnd = 0;
}
+ resetResolvedDrawables();
+ resolveDrawables();
}
}
diff --git a/core/java/com/android/internal/app/PlatLogoActivity.java b/core/java/com/android/internal/app/PlatLogoActivity.java
index 3a2b647..91c47d1 100644
--- a/core/java/com/android/internal/app/PlatLogoActivity.java
+++ b/core/java/com/android/internal/app/PlatLogoActivity.java
@@ -18,91 +18,96 @@ package com.android.internal.app;
import android.app.Activity;
import android.content.ActivityNotFoundException;
+import android.content.Context;
import android.content.Intent;
import android.graphics.Typeface;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.text.method.AllCapsTransformationMethod;
+import android.text.method.TransformationMethod;
import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class PlatLogoActivity extends Activity {
- Toast mToast;
- ImageView mContent;
+ FrameLayout mContent;
int mCount;
final Handler mHandler = new Handler();
- private View makeView() {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
- LinearLayout view = new LinearLayout(this);
- view.setOrientation(LinearLayout.VERTICAL);
- view.setLayoutParams(
- new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT
- ));
- final int p = (int)(8 * metrics.density);
- view.setPadding(p, p, p, p);
-
+ Typeface bold = Typeface.create("sans-serif", Typeface.BOLD);
Typeface light = Typeface.create("sans-serif-light", Typeface.NORMAL);
- Typeface normal = Typeface.create("sans-serif", Typeface.BOLD);
- final float size = 14 * metrics.density;
- final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
- LinearLayout.LayoutParams.WRAP_CONTENT,
- LinearLayout.LayoutParams.WRAP_CONTENT);
- lp.gravity = Gravity.CENTER_HORIZONTAL;
- lp.bottomMargin = (int) (-4*metrics.density);
+ mContent = new FrameLayout(this);
+
+ final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.WRAP_CONTENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT);
+ lp.gravity = Gravity.CENTER;
- TextView tv = new TextView(this);
+ final ImageView logo = new ImageView(this);
+ logo.setImageResource(com.android.internal.R.drawable.platlogo);
+ logo.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ logo.setVisibility(View.INVISIBLE);
+
+ final TextView letter = new TextView(this);
+
+ letter.setTypeface(bold);
+ letter.setTextSize(300);
+ letter.setTextColor(0xFFFFFFFF);
+ letter.setGravity(Gravity.CENTER);
+ letter.setShadowLayer(12*metrics.density, 0, 0, 0xC085F985);
+ letter.setText(String.valueOf(Build.VERSION.RELEASE).substring(0, 1));
+
+ final int p = (int)(4 * metrics.density);
+
+ final TextView tv = new TextView(this);
if (light != null) tv.setTypeface(light);
- tv.setTextSize(1.25f*size);
+ tv.setTextSize(30);
+ tv.setPadding(p, p, p, p);
tv.setTextColor(0xFFFFFFFF);
- tv.setShadowLayer(4*metrics.density, 0, 2*metrics.density, 0x66000000);
+ tv.setGravity(Gravity.CENTER);
+ tv.setShadowLayer(4 * metrics.density, 0, 2 * metrics.density, 0x66000000);
+ tv.setTransformationMethod(new AllCapsTransformationMethod(this));
tv.setText("Android " + Build.VERSION.RELEASE);
- view.addView(tv, lp);
-
- tv = new TextView(this);
- if (normal != null) tv.setTypeface(normal);
- tv.setTextSize(size);
- tv.setTextColor(0xFFFFFFFF);
- tv.setShadowLayer(4*metrics.density, 0, 2*metrics.density, 0x66000000);
- tv.setText("JELLY BEAN");
- view.addView(tv, lp);
+ tv.setVisibility(View.INVISIBLE);
- return view;
- }
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
+ mContent.addView(letter, lp);
+ mContent.addView(logo, lp);
- mToast = Toast.makeText(this, "", Toast.LENGTH_LONG);
- mToast.setView(makeView());
+ final FrameLayout.LayoutParams lp2 = new FrameLayout.LayoutParams(lp);
+ lp2.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
+ lp2.bottomMargin = 10*p;
- DisplayMetrics metrics = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
-
- mContent = new ImageView(this);
- mContent.setImageResource(com.android.internal.R.drawable.platlogo_alt);
- mContent.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-
- final int p = (int)(32 * metrics.density);
- mContent.setPadding(p, p, p, p);
+ mContent.addView(tv, lp2);
mContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- mToast.show();
- mContent.setImageResource(com.android.internal.R.drawable.platlogo);
+ if (logo.getVisibility() != View.VISIBLE) {
+ letter.animate().alpha(0.25f).scaleY(0.75f).scaleX(0.75f).setDuration(2000)
+ .start();
+ logo.setAlpha(0f);
+ logo.setVisibility(View.VISIBLE);
+ logo.animate().alpha(1f).setDuration(1000).setStartDelay(500).start();
+ tv.setAlpha(0f);
+ tv.setVisibility(View.VISIBLE);
+ tv.animate().alpha(1f).setDuration(1000).setStartDelay(1000).start();
+ }
}
});
@@ -115,9 +120,8 @@ public class PlatLogoActivity extends Activity {
| Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
.addCategory("com.android.internal.category.PLATLOGO"));
- //.setClassName("com.android.systemui","com.android.systemui.BeanBag"));
} catch (ActivityNotFoundException ex) {
- android.util.Log.e("PlatLogoActivity", "Couldn't find a bag of beans.");
+ android.util.Log.e("PlatLogoActivity", "Couldn't find a piece of pie.");
}
finish();
return true;
diff --git a/services/java/com/android/server/ProcessMap.java b/core/java/com/android/internal/app/ProcessMap.java
index 20c97ba..6ff0304 100644
--- a/services/java/com/android/server/ProcessMap.java
+++ b/core/java/com/android/internal/app/ProcessMap.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.internal.app;
import android.util.ArrayMap;
import android.util.SparseArray;
diff --git a/services/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 5e9b6a1..7eadbb5 100644
--- a/services/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -29,9 +29,10 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import android.webkit.WebViewFactory;
import com.android.internal.util.ArrayUtils;
-import com.android.server.ProcessMap;
import dalvik.system.VMRuntime;
+import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
@@ -39,10 +40,12 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Objects;
-final public class ProcessStats implements Parcelable {
+public final class ProcessStats implements Parcelable {
static final String TAG = "ProcessStats";
static final boolean DEBUG = false;
-
+
+ public static final String SERVICE_NAME = "procstats";
+
public static final int STATE_NOTHING = -1;
public static final int STATE_PERSISTENT = 0;
public static final int STATE_TOP = 1;
@@ -84,13 +87,20 @@ final public class ProcessStats implements Parcelable {
public static final int FLAG_SHUTDOWN = 1<<1;
public static final int FLAG_SYSPROPS = 1<<2;
- static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL, ADJ_MEM_FACTOR_MODERATE,
- ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
- static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
- static final int[] NON_CACHED_PROC_STATES = new int[] { STATE_PERSISTENT,
- STATE_TOP, STATE_IMPORTANT_FOREGROUND,
+ public static final int[] ALL_MEM_ADJ = new int[] { ADJ_MEM_FACTOR_NORMAL,
+ ADJ_MEM_FACTOR_MODERATE, ADJ_MEM_FACTOR_LOW, ADJ_MEM_FACTOR_CRITICAL };
+
+ public static final int[] ALL_SCREEN_ADJ = new int[] { ADJ_SCREEN_OFF, ADJ_SCREEN_ON };
+
+ public static final int[] NON_CACHED_PROC_STATES = new int[] {
+ STATE_PERSISTENT, STATE_TOP, STATE_IMPORTANT_FOREGROUND,
STATE_IMPORTANT_BACKGROUND, STATE_BACKUP, STATE_HEAVY_WEIGHT,
- STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER, STATE_HOME
+ STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
+ };
+
+ public static final int[] BACKGROUND_PROC_STATES = new int[] {
+ STATE_IMPORTANT_FOREGROUND, STATE_IMPORTANT_BACKGROUND, STATE_BACKUP,
+ STATE_HEAVY_WEIGHT, STATE_SERVICE, STATE_SERVICE_RESTARTING, STATE_RECEIVER
};
// Map from process states to the states we track.
@@ -204,6 +214,80 @@ final public class ProcessStats implements Parcelable {
readFromParcel(in);
}
+ public void add(ProcessStats other) {
+ ArrayMap<String, SparseArray<PackageState>> pkgMap = other.mPackages.getMap();
+ for (int ip=0; ip<pkgMap.size(); ip++) {
+ String pkgName = pkgMap.keyAt(ip);
+ SparseArray<PackageState> uids = pkgMap.valueAt(ip);
+ for (int iu=0; iu<uids.size(); iu++) {
+ int uid = uids.keyAt(iu);
+ PackageState otherState = uids.valueAt(iu);
+ final int NPROCS = otherState.mProcesses.size();
+ final int NSRVS = otherState.mServices.size();
+ for (int iproc=0; iproc<NPROCS; iproc++) {
+ ProcessState otherProc = otherState.mProcesses.valueAt(iproc);
+ if (otherProc.mCommonProcess != otherProc) {
+ if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+ + " proc " + otherProc.mName);
+ ProcessState thisProc = getProcessStateLocked(pkgName, uid,
+ otherProc.mName);
+ if (thisProc.mCommonProcess == thisProc) {
+ if (DEBUG) Slog.d(TAG, "Existing process is single-package, splitting");
+ thisProc.mMultiPackage = true;
+ long now = SystemClock.uptimeMillis();
+ final PackageState pkgState = getPackageStateLocked(pkgName, uid);
+ thisProc = thisProc.clone(thisProc.mPackage, now);
+ pkgState.mProcesses.put(thisProc.mName, thisProc);
+ }
+ thisProc.add(otherProc);
+ }
+ }
+ for (int isvc=0; isvc<NSRVS; isvc++) {
+ ServiceState otherSvc = otherState.mServices.valueAt(isvc);
+ if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+ + " service " + otherSvc.mName);
+ ServiceState thisSvc = getServiceStateLocked(pkgName, uid,
+ null, otherSvc.mName);
+ thisSvc.add(otherSvc);
+ }
+ }
+ }
+
+ ArrayMap<String, SparseArray<ProcessState>> procMap = other.mProcesses.getMap();
+ for (int ip=0; ip<procMap.size(); ip++) {
+ SparseArray<ProcessState> uids = procMap.valueAt(ip);
+ for (int iu=0; iu<uids.size(); iu++) {
+ int uid = uids.keyAt(iu);
+ ProcessState otherProc = uids.valueAt(iu);
+ ProcessState thisProc = mProcesses.get(otherProc.mName, uid);
+ if (DEBUG) Slog.d(TAG, "Adding uid " + uid + " proc " + otherProc.mName);
+ if (thisProc == null) {
+ if (DEBUG) Slog.d(TAG, "Creating new process!");
+ thisProc = new ProcessState(this, otherProc.mPackage, uid, otherProc.mName);
+ mProcesses.put(otherProc.mName, uid, thisProc);
+ PackageState thisState = getPackageStateLocked(otherProc.mPackage, uid);
+ if (!thisState.mProcesses.containsKey(otherProc.mName)) {
+ thisState.mProcesses.put(otherProc.mName, thisProc);
+ }
+ }
+ thisProc.add(otherProc);
+ }
+ }
+
+ for (int i=0; i<ADJ_COUNT; i++) {
+ if (DEBUG) Slog.d(TAG, "Total duration #" + i + " inc by "
+ + other.mMemFactorDurations[i] + " from "
+ + mMemFactorDurations[i]);
+ mMemFactorDurations[i] += other.mMemFactorDurations[i];
+ }
+
+ if (other.mTimePeriodStartClock < mTimePeriodStartClock) {
+ mTimePeriodStartClock = other.mTimePeriodStartClock;
+ mTimePeriodStartClockStr = other.mTimePeriodStartClockStr;
+ }
+ mTimePeriodEndRealtime += other.mTimePeriodEndRealtime - other.mTimePeriodStartRealtime;
+ }
+
public static final Parcelable.Creator<ProcessStats> CREATOR
= new Parcelable.Creator<ProcessStats>() {
public ProcessStats createFromParcel(Parcel in) {
@@ -215,7 +299,7 @@ final public class ProcessStats implements Parcelable {
}
};
- static private void printScreenLabel(PrintWriter pw, int offset) {
+ private static void printScreenLabel(PrintWriter pw, int offset) {
switch (offset) {
case ADJ_NOTHING:
pw.print(" ");
@@ -232,7 +316,7 @@ final public class ProcessStats implements Parcelable {
}
}
- static public void printScreenLabelCsv(PrintWriter pw, int offset) {
+ public static void printScreenLabelCsv(PrintWriter pw, int offset) {
switch (offset) {
case ADJ_NOTHING:
break;
@@ -248,7 +332,7 @@ final public class ProcessStats implements Parcelable {
}
}
- static private void printMemLabel(PrintWriter pw, int offset) {
+ private static void printMemLabel(PrintWriter pw, int offset) {
switch (offset) {
case ADJ_NOTHING:
pw.print(" ");
@@ -271,7 +355,7 @@ final public class ProcessStats implements Parcelable {
}
}
- static public void printMemLabelCsv(PrintWriter pw, int offset) {
+ public static void printMemLabelCsv(PrintWriter pw, int offset) {
if (offset >= ADJ_MEM_FACTOR_NORMAL) {
if (offset <= ADJ_MEM_FACTOR_CRITICAL) {
pw.print(ADJ_MEM_NAMES_CSV[offset]);
@@ -281,7 +365,7 @@ final public class ProcessStats implements Parcelable {
}
}
- static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
+ public static long dumpSingleTime(PrintWriter pw, String prefix, long[] durations,
int curState, long curStartTime, long now) {
long totalTime = 0;
int printedScreen = -1;
@@ -361,7 +445,7 @@ final public class ProcessStats implements Parcelable {
if (type != serviceType) {
continue;
}
- long time = svc.mProcessStats.getLong(off, 0);
+ long time = svc.mStats.getLong(off, 0);
if (curState == memFactor) {
didCurState = true;
time += now - curStartTime;
@@ -374,7 +458,7 @@ final public class ProcessStats implements Parcelable {
pw.println();
}
- static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) {
+ public static void computeProcessData(ProcessState proc, ProcessDataCollection data, long now) {
data.totalTime = 0;
data.numPss = data.minPss = data.avgPss = data.maxPss =
data.minUss = data.avgUss = data.maxUss = 0;
@@ -815,7 +899,7 @@ final public class ProcessStats implements Parcelable {
for (int i=0; i<proc.mDurationsTableSize; i++) {
int off = proc.mDurationsTable[i];
int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
- long time = proc.mProcessStats.getLong(off, 0);
+ long time = proc.mStats.getLong(off, 0);
if (proc.mCurState == type) {
didCurState = true;
time += now - proc.mStartTime;
@@ -831,13 +915,13 @@ final public class ProcessStats implements Parcelable {
for (int i=0; i<proc.mPssTableSize; i++) {
int off = proc.mPssTable[i];
int type = (off>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
- long count = proc.mProcessStats.getLong(off, PSS_SAMPLE_COUNT);
- long min = proc.mProcessStats.getLong(off, PSS_MINIMUM);
- long avg = proc.mProcessStats.getLong(off, PSS_AVERAGE);
- long max = proc.mProcessStats.getLong(off, PSS_MAXIMUM);
- long umin = proc.mProcessStats.getLong(off, PSS_USS_MINIMUM);
- long uavg = proc.mProcessStats.getLong(off, PSS_USS_AVERAGE);
- long umax = proc.mProcessStats.getLong(off, PSS_USS_MAXIMUM);
+ long count = proc.mStats.getLong(off, PSS_SAMPLE_COUNT);
+ long min = proc.mStats.getLong(off, PSS_MINIMUM);
+ long avg = proc.mStats.getLong(off, PSS_AVERAGE);
+ long max = proc.mStats.getLong(off, PSS_MAXIMUM);
+ long umin = proc.mStats.getLong(off, PSS_USS_MINIMUM);
+ long uavg = proc.mStats.getLong(off, PSS_USS_AVERAGE);
+ long umax = proc.mStats.getLong(off, PSS_USS_MAXIMUM);
pw.print(',');
printProcStateTag(pw, type);
pw.print(':');
@@ -979,6 +1063,37 @@ final public class ProcessStats implements Parcelable {
out.writeInt(PSS_COUNT);
out.writeInt(LONGS_SIZE);
+ // First commit all running times.
+ ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
+ final int NPROC = procMap.size();
+ for (int ip=0; ip<NPROC; ip++) {
+ SparseArray<ProcessState> uids = procMap.valueAt(ip);
+ final int NUID = uids.size();
+ for (int iu=0; iu<NUID; iu++) {
+ uids.valueAt(iu).commitStateTime(now);
+ }
+ }
+ ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
+ final int NPKG = pkgMap.size();
+ for (int ip=0; ip<NPKG; ip++) {
+ SparseArray<PackageState> uids = pkgMap.valueAt(ip);
+ final int NUID = uids.size();
+ for (int iu=0; iu<NUID; iu++) {
+ PackageState pkgState = uids.valueAt(iu);
+ final int NPROCS = pkgState.mProcesses.size();
+ for (int iproc=0; iproc<NPROCS; iproc++) {
+ ProcessState proc = pkgState.mProcesses.valueAt(iproc);
+ if (proc.mCommonProcess != proc) {
+ proc.commitStateTime(now);
+ }
+ }
+ final int NSRVS = pkgState.mServices.size();
+ for (int isvc=0; isvc<NSRVS; isvc++) {
+ pkgState.mServices.valueAt(isvc).commitStateTime(now);
+ }
+ }
+ }
+
out.writeLong(mTimePeriodStartClock);
out.writeLong(mTimePeriodStartRealtime);
out.writeLong(mTimePeriodEndRealtime);
@@ -991,7 +1106,7 @@ final public class ProcessStats implements Parcelable {
for (int i=0; i<(mLongs.size()-1); i++) {
out.writeLongArray(mLongs.get(i));
}
- long[] lastLongs = mLongs.get(mLongs.size()-1);
+ long[] lastLongs = mLongs.get(mLongs.size() - 1);
for (int i=0; i<mNextLong; i++) {
out.writeLong(lastLongs[i]);
if (DEBUG) Slog.d(TAG, "Writing last long #" + i + ": " + lastLongs[i]);
@@ -1003,8 +1118,6 @@ final public class ProcessStats implements Parcelable {
}
out.writeLongArray(mMemFactorDurations);
- ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
- final int NPROC = procMap.size();
out.writeInt(NPROC);
for (int ip=0; ip<NPROC; ip++) {
out.writeString(procMap.keyAt(ip));
@@ -1018,8 +1131,6 @@ final public class ProcessStats implements Parcelable {
proc.writeToParcel(out, now);
}
}
- ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
- final int NPKG = pkgMap.size();
out.writeInt(NPKG);
for (int ip=0; ip<NPKG; ip++) {
out.writeString(pkgMap.keyAt(ip));
@@ -1063,6 +1174,43 @@ final public class ProcessStats implements Parcelable {
return true;
}
+ static byte[] readFully(InputStream stream) throws IOException {
+ int pos = 0;
+ int avail = stream.available();
+ byte[] data = new byte[avail];
+ while (true) {
+ int amt = stream.read(data, pos, data.length-pos);
+ //Log.i("foo", "Read " + amt + " bytes at " + pos
+ // + " of avail " + data.length);
+ if (amt <= 0) {
+ //Log.i("foo", "**** FINISHED READING: pos=" + pos
+ // + " len=" + data.length);
+ return data;
+ }
+ pos += amt;
+ avail = stream.available();
+ if (avail > data.length-pos) {
+ byte[] newData = new byte[pos+avail];
+ System.arraycopy(data, 0, newData, 0, pos);
+ data = newData;
+ }
+ }
+ }
+
+ public void read(InputStream stream) {
+ try {
+ byte[] raw = readFully(stream);
+ Parcel in = Parcel.obtain();
+ in.unmarshall(raw, 0, raw.length);
+ in.setDataPosition(0);
+ stream.close();
+
+ readFromParcel(in);
+ } catch (IOException e) {
+ mReadError = "caught exception: " + e;
+ }
+ }
+
public void readFromParcel(Parcel in) {
final boolean hadData = mPackages.getMap().size() > 0
|| mProcesses.getMap().size() > 0;
@@ -1254,7 +1402,7 @@ final public class ProcessStats implements Parcelable {
}
ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
if (serv == null) {
- serv = new ServiceState(this, pkgName, null);
+ serv = new ServiceState(this, pkgName, serviceName, null);
}
if (!serv.readFromParcel(in)) {
return;
@@ -1402,6 +1550,21 @@ final public class ProcessStats implements Parcelable {
return ps;
}
+ public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid,
+ String processName, String className) {
+ final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid);
+ ProcessStats.ServiceState ss = as.mServices.get(className);
+ if (ss != null) {
+ ss.makeActive();
+ return ss;
+ }
+ final ProcessStats.ProcessState ps = processName != null
+ ? getProcessStateLocked(packageName, uid, processName) : null;
+ ss = new ProcessStats.ServiceState(this, packageName, className, ps);
+ as.mServices.put(className, ss);
+ return ss;
+ }
+
public void dumpLocked(PrintWriter pw, String reqPackage, long now, boolean dumpAll) {
long totalTime = dumpSingleTime(null, null, mMemFactorDurations, mMemFactor,
mStartTime, now);
@@ -1530,11 +1693,8 @@ final public class ProcessStats implements Parcelable {
long time = service.getDuration(serviceType, curState, curStartTime,
state, now);
String running = "";
- if (curState == state) {
- time += now - curStartTime;
- if (pw != null) {
- running = " (running)";
- }
+ if (curState == state && pw != null) {
+ running = " (running)";
}
if (time != 0) {
if (pw != null) {
@@ -1824,11 +1984,11 @@ final public class ProcessStats implements Parcelable {
}
public static final class ProcessState {
- final ProcessStats mProcessStats;
- final ProcessState mCommonProcess;
- final String mPackage;
- final int mUid;
- final String mName;
+ public final ProcessStats mStats;
+ public final ProcessState mCommonProcess;
+ public final String mPackage;
+ public final int mUid;
+ public final String mName;
int[] mDurationsTable;
int mDurationsTableSize;
@@ -1849,14 +2009,14 @@ final public class ProcessStats implements Parcelable {
boolean mMultiPackage;
- long mTmpTotalTime;
+ public long mTmpTotalTime;
/**
* Create a new top-level process state, for the initial case where there is only
* a single package running in a process. The initial state is not running.
*/
public ProcessState(ProcessStats processStats, String pkg, int uid, String name) {
- mProcessStats = processStats;
+ mStats = processStats;
mCommonProcess = this;
mPackage = pkg;
mUid = uid;
@@ -1870,7 +2030,7 @@ final public class ProcessStats implements Parcelable {
*/
public ProcessState(ProcessState commonProcess, String pkg, int uid, String name,
long now) {
- mProcessStats = commonProcess.mProcessStats;
+ mStats = commonProcess.mStats;
mCommonProcess = commonProcess;
mPackage = pkg;
mUid = uid;
@@ -1882,32 +2042,32 @@ final public class ProcessStats implements Parcelable {
ProcessState clone(String pkg, long now) {
ProcessState pnew = new ProcessState(this, pkg, mUid, mName, now);
if (mDurationsTable != null) {
- mProcessStats.mAddLongTable = new int[mDurationsTable.length];
- mProcessStats.mAddLongTableSize = 0;
+ mStats.mAddLongTable = new int[mDurationsTable.length];
+ mStats.mAddLongTableSize = 0;
for (int i=0; i<mDurationsTableSize; i++) {
int origEnt = mDurationsTable[i];
int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
- int newOff = mProcessStats.addLongData(i, type, 1);
- mProcessStats.mAddLongTable[i] = newOff | type;
- mProcessStats.setLong(newOff, 0, mProcessStats.getLong(origEnt, 0));
+ int newOff = mStats.addLongData(i, type, 1);
+ mStats.mAddLongTable[i] = newOff | type;
+ mStats.setLong(newOff, 0, mStats.getLong(origEnt, 0));
}
- pnew.mDurationsTable = mProcessStats.mAddLongTable;
- pnew.mDurationsTableSize = mProcessStats.mAddLongTableSize;
+ pnew.mDurationsTable = mStats.mAddLongTable;
+ pnew.mDurationsTableSize = mStats.mAddLongTableSize;
}
if (mPssTable != null) {
- mProcessStats.mAddLongTable = new int[mPssTable.length];
- mProcessStats.mAddLongTableSize = 0;
+ mStats.mAddLongTable = new int[mPssTable.length];
+ mStats.mAddLongTableSize = 0;
for (int i=0; i<mPssTableSize; i++) {
int origEnt = mPssTable[i];
int type = (origEnt>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
- int newOff = mProcessStats.addLongData(i, type, PSS_COUNT);
- mProcessStats.mAddLongTable[i] = newOff | type;
+ int newOff = mStats.addLongData(i, type, PSS_COUNT);
+ mStats.mAddLongTable[i] = newOff | type;
for (int j=0; j<PSS_COUNT; j++) {
- mProcessStats.setLong(newOff, j, mProcessStats.getLong(origEnt, j));
+ mStats.setLong(newOff, j, mStats.getLong(origEnt, j));
}
}
- pnew.mPssTable = mProcessStats.mAddLongTable;
- pnew.mPssTableSize = mProcessStats.mAddLongTableSize;
+ pnew.mPssTable = mStats.mAddLongTable;
+ pnew.mPssTableSize = mStats.mAddLongTableSize;
}
pnew.mNumExcessiveWake = mNumExcessiveWake;
pnew.mNumExcessiveCpu = mNumExcessiveCpu;
@@ -1915,6 +2075,29 @@ final public class ProcessStats implements Parcelable {
return pnew;
}
+ void add(ProcessState other) {
+ for (int i=0; i<other.mDurationsTableSize; i++) {
+ int ent = other.mDurationsTable[i];
+ int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ if (DEBUG) Slog.d(TAG, "Adding state " + state + " duration "
+ + other.mStats.getLong(ent, 0));
+ addDuration(state, other.mStats.getLong(ent, 0));
+ }
+ for (int i=0; i<other.mPssTableSize; i++) {
+ int ent = other.mPssTable[i];
+ int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ addPss(state, (int) other.mStats.getLong(ent, PSS_SAMPLE_COUNT),
+ other.mStats.getLong(ent, PSS_MINIMUM),
+ other.mStats.getLong(ent, PSS_AVERAGE),
+ other.mStats.getLong(ent, PSS_MAXIMUM),
+ other.mStats.getLong(ent, PSS_USS_MINIMUM),
+ other.mStats.getLong(ent, PSS_USS_AVERAGE),
+ other.mStats.getLong(ent, PSS_USS_MAXIMUM));
+ }
+ mNumExcessiveWake += other.mNumExcessiveWake;
+ mNumExcessiveCpu += other.mNumExcessiveCpu;
+ }
+
void resetSafely(long now) {
mDurationsTable = null;
mDurationsTableSize = 0;
@@ -1928,7 +2111,6 @@ final public class ProcessStats implements Parcelable {
}
void writeToParcel(Parcel out, long now) {
- commitStateTime(now);
out.writeInt(mMultiPackage ? 1 : 0);
out.writeInt(mDurationsTableSize);
for (int i=0; i<mDurationsTableSize; i++) {
@@ -1952,13 +2134,13 @@ final public class ProcessStats implements Parcelable {
mMultiPackage = multiPackage;
}
if (DEBUG) Slog.d(TAG, "Reading durations table...");
- mDurationsTable = mProcessStats.readTableFromParcel(in, mName, "durations");
+ mDurationsTable = mStats.readTableFromParcel(in, mName, "durations");
if (mDurationsTable == BAD_TABLE) {
return false;
}
mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
if (DEBUG) Slog.d(TAG, "Reading pss table...");
- mPssTable = mProcessStats.readTableFromParcel(in, mName, "pss");
+ mPssTable = mStats.readTableFromParcel(in, mName, "pss");
if (mPssTable == BAD_TABLE) {
return false;
}
@@ -2012,24 +2194,30 @@ final public class ProcessStats implements Parcelable {
if (mCurState != STATE_NOTHING) {
long dur = now - mStartTime;
if (dur > 0) {
- int idx = binarySearch(mDurationsTable, mDurationsTableSize, mCurState);
- int off;
- if (idx >= 0) {
- off = mDurationsTable[idx];
- } else {
- mProcessStats.mAddLongTable = mDurationsTable;
- mProcessStats.mAddLongTableSize = mDurationsTableSize;
- off = mProcessStats.addLongData(~idx, mCurState, 1);
- mDurationsTable = mProcessStats.mAddLongTable;
- mDurationsTableSize = mProcessStats.mAddLongTableSize;
- }
- long[] longs = mProcessStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
- longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
+ addDuration(mCurState, dur);
}
}
mStartTime = now;
}
+ void addDuration(int state, long dur) {
+ int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
+ int off;
+ if (idx >= 0) {
+ off = mDurationsTable[idx];
+ } else {
+ mStats.mAddLongTable = mDurationsTable;
+ mStats.mAddLongTableSize = mDurationsTableSize;
+ off = mStats.addLongData(~idx, state, 1);
+ mDurationsTable = mStats.mAddLongTable;
+ mDurationsTableSize = mStats.mAddLongTableSize;
+ }
+ long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ if (DEBUG) Slog.d(TAG, "Duration of " + mName + " state " + state + " inc by " + dur
+ + " from " + longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK]);
+ longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
+ }
+
void incStartedServices(int memFactor, long now) {
if (mCommonProcess != this) {
mCommonProcess.incStartedServices(memFactor, now);
@@ -2063,46 +2251,53 @@ final public class ProcessStats implements Parcelable {
mLastPssState = mCurState;
mLastPssTime = SystemClock.uptimeMillis();
if (mCurState != STATE_NOTHING) {
- int idx = binarySearch(mPssTable, mPssTableSize, mCurState);
- int off;
- if (idx >= 0) {
- off = mPssTable[idx];
- } else {
- mProcessStats.mAddLongTable = mPssTable;
- mProcessStats.mAddLongTableSize = mPssTableSize;
- off = mProcessStats.addLongData(~idx, mCurState, PSS_COUNT);
- mPssTable = mProcessStats.mAddLongTable;
- mPssTableSize = mProcessStats.mAddLongTableSize;
+ addPss(mCurState, 1, pss, pss, pss, uss, uss, uss);
+ }
+ }
+
+ void addPss(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss,
+ long avgUss, long maxUss) {
+ int idx = binarySearch(mPssTable, mPssTableSize, state);
+ int off;
+ if (idx >= 0) {
+ off = mPssTable[idx];
+ } else {
+ mStats.mAddLongTable = mPssTable;
+ mStats.mAddLongTableSize = mPssTableSize;
+ off = mStats.addLongData(~idx, state, PSS_COUNT);
+ mPssTable = mStats.mAddLongTable;
+ mPssTableSize = mStats.mAddLongTableSize;
+ }
+ long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
+ long count = longs[idx+PSS_SAMPLE_COUNT];
+ if (count == 0) {
+ longs[idx+PSS_SAMPLE_COUNT] = inCount;
+ longs[idx+PSS_MINIMUM] = minPss;
+ longs[idx+PSS_AVERAGE] = avgPss;
+ longs[idx+PSS_MAXIMUM] = maxPss;
+ longs[idx+PSS_USS_MINIMUM] = minUss;
+ longs[idx+PSS_USS_AVERAGE] = avgUss;
+ longs[idx+PSS_USS_MAXIMUM] = maxUss;
+ } else {
+ longs[idx+PSS_SAMPLE_COUNT] = count+inCount;
+ if (longs[idx+PSS_MINIMUM] > minPss) {
+ longs[idx+PSS_MINIMUM] = minPss;
}
- long[] longs = mProcessStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
- idx = (off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK;
- long count = longs[idx+PSS_SAMPLE_COUNT];
- if (count == 0) {
- longs[idx+PSS_SAMPLE_COUNT] = 1;
- longs[idx+PSS_MINIMUM] = pss;
- longs[idx+PSS_AVERAGE] = pss;
- longs[idx+PSS_MAXIMUM] = pss;
- longs[idx+PSS_USS_MINIMUM] = uss;
- longs[idx+PSS_USS_AVERAGE] = uss;
- longs[idx+PSS_USS_MAXIMUM] = uss;
- } else {
- longs[idx+PSS_SAMPLE_COUNT] = count+1;
- if (longs[idx+PSS_MINIMUM] > pss) {
- longs[idx+PSS_MINIMUM] = pss;
- }
- longs[idx+PSS_AVERAGE] = (long)(
- ((longs[idx+PSS_AVERAGE]*(double)count)+pss) / (count+1) );
- if (longs[idx+PSS_MAXIMUM] < pss) {
- longs[idx+PSS_MAXIMUM] = pss;
- }
- if (longs[idx+PSS_USS_MINIMUM] > uss) {
- longs[idx+PSS_USS_MINIMUM] = uss;
- }
- longs[idx+PSS_USS_AVERAGE] = (long)(
- ((longs[idx+PSS_USS_AVERAGE]*(double)count)+uss) / (count+1) );
- if (longs[idx+PSS_USS_MAXIMUM] < uss) {
- longs[idx+PSS_USS_MAXIMUM] = uss;
- }
+ longs[idx+PSS_AVERAGE] = (long)(
+ ((longs[idx+PSS_AVERAGE]*(double)count)+(avgPss*(double)inCount))
+ / (count+inCount) );
+ if (longs[idx+PSS_MAXIMUM] < maxPss) {
+ longs[idx+PSS_MAXIMUM] = maxPss;
+ }
+ if (longs[idx+PSS_USS_MINIMUM] > minUss) {
+ longs[idx+PSS_USS_MINIMUM] = minUss;
+ }
+ longs[idx+PSS_USS_AVERAGE] = (long)(
+ ((longs[idx+PSS_USS_AVERAGE]*(double)count)+(avgUss*(double)inCount))
+ / (count+inCount) );
+ if (longs[idx+PSS_USS_MAXIMUM] < maxUss) {
+ longs[idx+PSS_USS_MAXIMUM] = maxUss;
}
}
}
@@ -2134,7 +2329,7 @@ final public class ProcessStats implements Parcelable {
// The array map is still pointing to a common process state
// that is now shared across packages. Update it to point to
// the new per-package state.
- ProcessState proc = mProcessStats.mPackages.get(pkgName,
+ ProcessState proc = mStats.mPackages.get(pkgName,
mUid).mProcesses.get(mName);
if (proc == null) {
throw new IllegalStateException("Didn't create per-package process");
@@ -2151,7 +2346,7 @@ final public class ProcessStats implements Parcelable {
// The array map is still pointing to a common process state
// that is now shared across packages. Update it to point to
// the new per-package state.
- proc = mProcessStats.mPackages.get(pkgList.keyAt(index),
+ proc = mStats.mPackages.get(pkgList.keyAt(index),
proc.mUid).mProcesses.get(proc.mName);
if (proc == null) {
throw new IllegalStateException("Didn't create per-package process");
@@ -2163,7 +2358,7 @@ final public class ProcessStats implements Parcelable {
long getDuration(int state, long now) {
int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
- long time = idx >= 0 ? mProcessStats.getLong(mDurationsTable[idx], 0) : 0;
+ long time = idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0;
if (mCurState == state) {
time += now - mStartTime;
}
@@ -2172,43 +2367,44 @@ final public class ProcessStats implements Parcelable {
long getPssSampleCount(int state) {
int idx = binarySearch(mPssTable, mPssTableSize, state);
- return idx >= 0 ? mProcessStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
+ return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_SAMPLE_COUNT) : 0;
}
long getPssMinimum(int state) {
int idx = binarySearch(mPssTable, mPssTableSize, state);
- return idx >= 0 ? mProcessStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
+ return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MINIMUM) : 0;
}
long getPssAverage(int state) {
int idx = binarySearch(mPssTable, mPssTableSize, state);
- return idx >= 0 ? mProcessStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
+ return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_AVERAGE) : 0;
}
long getPssMaximum(int state) {
int idx = binarySearch(mPssTable, mPssTableSize, state);
- return idx >= 0 ? mProcessStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
+ return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_MAXIMUM) : 0;
}
long getPssUssMinimum(int state) {
int idx = binarySearch(mPssTable, mPssTableSize, state);
- return idx >= 0 ? mProcessStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
+ return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MINIMUM) : 0;
}
long getPssUssAverage(int state) {
int idx = binarySearch(mPssTable, mPssTableSize, state);
- return idx >= 0 ? mProcessStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
+ return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_AVERAGE) : 0;
}
long getPssUssMaximum(int state) {
int idx = binarySearch(mPssTable, mPssTableSize, state);
- return idx >= 0 ? mProcessStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
+ return idx >= 0 ? mStats.getLong(mPssTable[idx], PSS_USS_MAXIMUM) : 0;
}
}
public static final class ServiceState {
- final ProcessStats mProcessStats;
+ final ProcessStats mStats;
final String mPackage;
+ final String mName;
ProcessState mProc;
int mActive = 1;
@@ -2233,9 +2429,10 @@ final public class ProcessStats implements Parcelable {
public int mExecState = STATE_NOTHING;
long mExecStartTime;
- public ServiceState(ProcessStats processStats, String pkg, ProcessState proc) {
- mProcessStats = processStats;
+ public ServiceState(ProcessStats processStats, String pkg, String name, ProcessState proc) {
+ mStats = processStats;
mPackage = pkg;
+ mName = name;
mProc = proc;
}
@@ -2256,6 +2453,17 @@ final public class ProcessStats implements Parcelable {
return mActive > 0;
}
+ void add(ServiceState other) {
+ for (int i=0; i<other.mDurationsTableSize; i++) {
+ int ent = other.mDurationsTable[i];
+ int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
+ addStateTime(state, other.mStats.getLong(ent, 0));
+ }
+ mStartedCount += other.mStartedCount;
+ mBoundCount += other.mBoundCount;
+ mExecCount += other.mExecCount;
+ }
+
void resetSafely(long now) {
mDurationsTable = null;
mDurationsTableSize = 0;
@@ -2266,18 +2474,6 @@ final public class ProcessStats implements Parcelable {
}
void writeToParcel(Parcel out, long now) {
- if (mStartedState != STATE_NOTHING) {
- addStateTime(SERVICE_STARTED, mStartedState, now - mStartedStartTime);
- mStartedStartTime = now;
- }
- if (mBoundState != STATE_NOTHING) {
- addStateTime(SERVICE_BOUND, mBoundState, now - mBoundStartTime);
- mBoundStartTime = now;
- }
- if (mExecState != STATE_NOTHING) {
- addStateTime(SERVICE_EXEC, mExecState, now - mExecStartTime);
- mExecStartTime = now;
- }
out.writeInt(mDurationsTableSize);
for (int i=0; i<mDurationsTableSize; i++) {
if (DEBUG) Slog.i(TAG, "Writing service in " + mPackage + " dur #" + i + ": "
@@ -2291,7 +2487,7 @@ final public class ProcessStats implements Parcelable {
boolean readFromParcel(Parcel in) {
if (DEBUG) Slog.d(TAG, "Reading durations table...");
- mDurationsTable = mProcessStats.readTableFromParcel(in, mPackage, "service");
+ mDurationsTable = mStats.readTableFromParcel(in, mPackage, "service");
if (mDurationsTable == BAD_TABLE) {
return false;
}
@@ -2302,25 +2498,40 @@ final public class ProcessStats implements Parcelable {
return true;
}
- void addStateTime(int opType, int memFactor, long time) {
+ void addStateTime(int state, long time) {
if (time > 0) {
- int state = opType + (memFactor*SERVICE_COUNT);
int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
int off;
if (idx >= 0) {
off = mDurationsTable[idx];
} else {
- mProcessStats.mAddLongTable = mDurationsTable;
- mProcessStats.mAddLongTableSize = mDurationsTableSize;
- off = mProcessStats.addLongData(~idx, state, 1);
- mDurationsTable = mProcessStats.mAddLongTable;
- mDurationsTableSize = mProcessStats.mAddLongTableSize;
+ mStats.mAddLongTable = mDurationsTable;
+ mStats.mAddLongTableSize = mDurationsTableSize;
+ off = mStats.addLongData(~idx, state, 1);
+ mDurationsTable = mStats.mAddLongTable;
+ mDurationsTableSize = mStats.mAddLongTableSize;
}
- long[] longs = mProcessStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
+ long[] longs = mStats.mLongs.get((off>>OFFSET_ARRAY_SHIFT)&OFFSET_ARRAY_MASK);
longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += time;
}
}
+ void commitStateTime(long now) {
+ if (mStartedState != STATE_NOTHING) {
+ addStateTime(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
+ now - mStartedStartTime);
+ mStartedStartTime = now;
+ }
+ if (mBoundState != STATE_NOTHING) {
+ addStateTime(SERVICE_BOUND + (mBoundState*SERVICE_COUNT), now - mBoundStartTime);
+ mBoundStartTime = now;
+ }
+ if (mExecState != STATE_NOTHING) {
+ addStateTime(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
+ mExecStartTime = now;
+ }
+ }
+
public void setStarted(boolean started, int memFactor, long now) {
if (mActive <= 0) {
throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
@@ -2328,7 +2539,8 @@ final public class ProcessStats implements Parcelable {
int state = started ? memFactor : STATE_NOTHING;
if (mStartedState != state) {
if (mStartedState != STATE_NOTHING) {
- addStateTime(SERVICE_STARTED, mStartedState, now - mStartedStartTime);
+ addStateTime(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
+ now - mStartedStartTime);
} else if (started) {
mStartedCount++;
}
@@ -2352,7 +2564,8 @@ final public class ProcessStats implements Parcelable {
int state = bound ? memFactor : STATE_NOTHING;
if (mBoundState != state) {
if (mBoundState != STATE_NOTHING) {
- addStateTime(SERVICE_BOUND, mBoundState, now - mBoundStartTime);
+ addStateTime(SERVICE_BOUND + (mBoundState*SERVICE_COUNT),
+ now - mBoundStartTime);
} else if (bound) {
mBoundCount++;
}
@@ -2368,7 +2581,7 @@ final public class ProcessStats implements Parcelable {
int state = executing ? memFactor : STATE_NOTHING;
if (mExecState != state) {
if (mExecState != STATE_NOTHING) {
- addStateTime(SERVICE_EXEC, mExecState, now - mExecStartTime);
+ addStateTime(SERVICE_EXEC + (mExecState*SERVICE_COUNT), now - mExecStartTime);
} else if (executing) {
mExecCount++;
}
@@ -2377,25 +2590,11 @@ final public class ProcessStats implements Parcelable {
}
}
- long getStartDuration(int opType, int memFactor, long now) {
- switch (opType) {
- case SERVICE_STARTED:
- return getDuration(opType, mStartedState, mStartedStartTime, memFactor, now);
- case SERVICE_BOUND:
- return getDuration(opType, mBoundState, mBoundStartTime, memFactor, now);
- case SERVICE_EXEC:
- return getDuration(opType, mExecState, mExecStartTime, memFactor, now);
- default:
- throw new IllegalArgumentException("Bad opType: " + opType);
- }
- }
-
-
private long getDuration(int opType, int curState, long startTime, int memFactor,
long now) {
int state = opType + (memFactor*SERVICE_COUNT);
int idx = binarySearch(mDurationsTable, mDurationsTableSize, state);
- long time = idx >= 0 ? mProcessStats.getLong(mDurationsTable[idx], 0) : 0;
+ long time = idx >= 0 ? mStats.getLong(mDurationsTable[idx], 0) : 0;
if (curState == memFactor) {
time += now - startTime;
}
@@ -2415,21 +2614,21 @@ final public class ProcessStats implements Parcelable {
}
}
- static final class ProcessDataCollection {
+ public static final class ProcessDataCollection {
final int[] screenStates;
final int[] memStates;
final int[] procStates;
- long totalTime;
- long numPss;
- long minPss;
- long avgPss;
- long maxPss;
- long minUss;
- long avgUss;
- long maxUss;
+ public long totalTime;
+ public long numPss;
+ public long minPss;
+ public long avgPss;
+ public long maxPss;
+ public long minUss;
+ public long avgUss;
+ public long maxUss;
- ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
+ public ProcessDataCollection(int[] _screenStates, int[] _memStates, int[] _procStates) {
screenStates = _screenStates;
memStates = _memStates;
procStates = _procStates;
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index ccc0089..04351da 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -499,7 +499,7 @@ public class ZygoteInit {
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003,3006,3007",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--runtime-init",
"--nice-name=system_server",
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 3308064..6c4526e 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -35,8 +35,6 @@
#include <utils/Log.h>
-#define TIME_DRAWx
-
static uint32_t get_thread_msec() {
#if defined(HAVE_POSIX_CLOCKS)
struct timespec tm;
@@ -463,20 +461,6 @@ public:
canvas->drawPath(*path, *paint);
}
- static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas,
- SkPicture* picture) {
- SkASSERT(canvas);
- SkASSERT(picture);
-
-#ifdef TIME_DRAW
- SkMSec now = get_thread_msec(); //SkTime::GetMSecs();
-#endif
- canvas->drawPicture(*picture);
-#ifdef TIME_DRAW
- ALOGD("---- picture playback %d ms\n", get_thread_msec() - now);
-#endif
- }
-
static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
SkCanvas* canvas, SkBitmap* bitmap,
jfloat left, jfloat top,
@@ -1103,7 +1087,6 @@ static JNINativeMethod gCanvasMethods[] = {
(void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
{"native_drawTextOnPath","(ILjava/lang/String;IFFII)V",
(void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
- {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
{"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index 2c482ea..bacfdf6 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -18,6 +18,9 @@
#include <stdio.h>
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+
#include <gui/GLConsumer.h>
#include <gui/Surface.h>
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 7e70c7c..6d23c32 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -141,7 +141,7 @@ static jboolean android_net_utils_runDhcpCommon(JNIEnv* env, jobject clazz, jstr
dns, server, &lease, vendorInfo, domains, mtu);
}
if (result != 0) {
- ALOGD("dhcp_do_request failed");
+ ALOGD("dhcp_do_request failed : %s (%s)", nameStr, renew ? "renew" : "new");
}
env->ReleaseStringUTFChars(ifname, nameStr);
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 08962e2..aa6dbf3 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -33,11 +33,11 @@ namespace android {
static jint DBG = false;
-static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuflen)
+static int doCommand(char *cmd, char *replybuf, int replybuflen)
{
size_t reply_len = replybuflen - 1;
- if (::wifi_command(ifname, cmd, BUF_SIZE, replybuf, &reply_len) != 0)
+ if (::wifi_command(cmd, replybuf, &reply_len) != 0)
return -1;
else {
// Strip off trailing newline
@@ -49,7 +49,7 @@ static int doCommand(const char *ifname, char *cmd, char *replybuf, int replybuf
}
}
-static jint doIntCommand(const char *ifname, const char* fmt, ...)
+static jint doIntCommand(const char* fmt, ...)
{
char buf[BUF_SIZE];
va_list args;
@@ -60,13 +60,13 @@ static jint doIntCommand(const char *ifname, const char* fmt, ...)
return -1;
}
char reply[BUF_SIZE];
- if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) {
+ if (doCommand(buf, reply, sizeof(reply)) != 0) {
return -1;
}
return static_cast<jint>(atoi(reply));
}
-static jboolean doBooleanCommand(const char *ifname, const char* expect, const char* fmt, ...)
+static jboolean doBooleanCommand(const char* expect, const char* fmt, ...)
{
char buf[BUF_SIZE];
va_list args;
@@ -77,14 +77,14 @@ static jboolean doBooleanCommand(const char *ifname, const char* expect, const c
return JNI_FALSE;
}
char reply[BUF_SIZE];
- if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) {
+ if (doCommand(buf, reply, sizeof(reply)) != 0) {
return JNI_FALSE;
}
return (strcmp(reply, expect) == 0);
}
// Send a command to the supplicant, and return the reply as a String
-static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt, ...) {
+static jstring doStringCommand(JNIEnv* env, const char* fmt, ...) {
char buf[BUF_SIZE];
va_list args;
va_start(args, fmt);
@@ -94,7 +94,7 @@ static jstring doStringCommand(JNIEnv* env, const char *ifname, const char* fmt,
return NULL;
}
char reply[4096];
- if (doCommand(ifname, buf, reply, sizeof(reply)) != 0) {
+ if (doCommand(buf, reply, sizeof(reply)) != 0) {
return NULL;
}
// TODO: why not just NewStringUTF?
@@ -127,23 +127,20 @@ static jboolean android_net_wifi_killSupplicant(JNIEnv* env, jobject, jboolean p
return (jboolean)(::wifi_stop_supplicant(p2pSupported) == 0);
}
-static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject, jstring jIface)
+static jboolean android_net_wifi_connectToSupplicant(JNIEnv* env, jobject)
{
- ScopedUtfChars ifname(env, jIface);
- return (jboolean)(::wifi_connect_to_supplicant(ifname.c_str()) == 0);
+ return (jboolean)(::wifi_connect_to_supplicant() == 0);
}
-static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject, jstring jIface)
+static void android_net_wifi_closeSupplicantConnection(JNIEnv* env, jobject)
{
- ScopedUtfChars ifname(env, jIface);
- ::wifi_close_supplicant_connection(ifname.c_str());
+ ::wifi_close_supplicant_connection();
}
-static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIface)
+static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject)
{
char buf[EVENT_BUF_SIZE];
- ScopedUtfChars ifname(env, jIface);
- int nread = ::wifi_wait_for_event(ifname.c_str(), buf, sizeof buf);
+ int nread = ::wifi_wait_for_event(buf, sizeof buf);
if (nread > 0) {
return env->NewStringUTF(buf);
} else {
@@ -151,43 +148,36 @@ static jstring android_net_wifi_waitForEvent(JNIEnv* env, jobject, jstring jIfac
}
}
-static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jIface,
- jstring jCommand)
+static jboolean android_net_wifi_doBooleanCommand(JNIEnv* env, jobject, jstring jCommand)
{
- ScopedUtfChars ifname(env, jIface);
ScopedUtfChars command(env, jCommand);
if (command.c_str() == NULL) {
return JNI_FALSE;
}
if (DBG) ALOGD("doBoolean: %s", command.c_str());
- return doBooleanCommand(ifname.c_str(), "OK", "%s", command.c_str());
+ return doBooleanCommand("OK", "%s", command.c_str());
}
-static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jIface,
- jstring jCommand)
+static jint android_net_wifi_doIntCommand(JNIEnv* env, jobject, jstring jCommand)
{
- ScopedUtfChars ifname(env, jIface);
ScopedUtfChars command(env, jCommand);
if (command.c_str() == NULL) {
return -1;
}
if (DBG) ALOGD("doInt: %s", command.c_str());
- return doIntCommand(ifname.c_str(), "%s", command.c_str());
+ return doIntCommand("%s", command.c_str());
}
-static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jIface,
- jstring jCommand)
+static jstring android_net_wifi_doStringCommand(JNIEnv* env, jobject, jstring jCommand)
{
- ScopedUtfChars ifname(env, jIface);
-
ScopedUtfChars command(env, jCommand);
if (command.c_str() == NULL) {
return NULL;
}
if (DBG) ALOGD("doString: %s", command.c_str());
- return doStringCommand(env, ifname.c_str(), "%s", command.c_str());
+ return doStringCommand(env, "%s", command.c_str());
}
@@ -205,17 +195,13 @@ static JNINativeMethod gWifiMethods[] = {
{ "unloadDriver", "()Z", (void *)android_net_wifi_unloadDriver },
{ "startSupplicant", "(Z)Z", (void *)android_net_wifi_startSupplicant },
{ "killSupplicant", "(Z)Z", (void *)android_net_wifi_killSupplicant },
- { "connectToSupplicant", "(Ljava/lang/String;)Z",
- (void *)android_net_wifi_connectToSupplicant },
- { "closeSupplicantConnection", "(Ljava/lang/String;)V",
+ { "connectToSupplicantNative", "()Z", (void *)android_net_wifi_connectToSupplicant },
+ { "closeSupplicantConnectionNative", "()V",
(void *)android_net_wifi_closeSupplicantConnection },
- { "waitForEvent", "(Ljava/lang/String;)Ljava/lang/String;",
- (void*) android_net_wifi_waitForEvent },
- { "doBooleanCommand", "(Ljava/lang/String;Ljava/lang/String;)Z",
- (void*) android_net_wifi_doBooleanCommand },
- { "doIntCommand", "(Ljava/lang/String;Ljava/lang/String;)I",
- (void*) android_net_wifi_doIntCommand },
- { "doStringCommand", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
+ { "waitForEventNative", "()Ljava/lang/String;", (void*)android_net_wifi_waitForEvent },
+ { "doBooleanCommandNative", "(Ljava/lang/String;)Z", (void*)android_net_wifi_doBooleanCommand },
+ { "doIntCommandNative", "(Ljava/lang/String;)I", (void*)android_net_wifi_doIntCommand },
+ { "doStringCommandNative", "(Ljava/lang/String;)Ljava/lang/String;",
(void*) android_net_wifi_doStringCommand },
};
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 61ace4a..f5eb389 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -220,6 +220,8 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
} else {
whichHeap = HEAP_ASHMEM;
}
+ } else if (strncmp(name, "[anon:libc_malloc]", 18) == 0) {
+ whichHeap = HEAP_NATIVE;
} else if (strncmp(name, "[stack", 6) == 0) {
whichHeap = HEAP_STACK;
} else if (strncmp(name, "/dev/", 5) == 0) {
@@ -246,6 +248,8 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
} else if (nameLen > 4 && strcmp(name+nameLen-4, ".art") == 0) {
whichHeap = HEAP_ART;
is_swappable = true;
+ } else if (strncmp(name, "[anon:", 6) == 0) {
+ whichHeap = HEAP_UNKNOWN;
} else if (nameLen > 0) {
whichHeap = HEAP_UNKNOWN_MAP;
} else if (start == prevEnd && prevHeap == HEAP_SO) {
diff --git a/core/jni/android_os_FileUtils.cpp b/core/jni/android_os_FileUtils.cpp
index 0aaa2b1..d1245da 100644
--- a/core/jni/android_os_FileUtils.cpp
+++ b/core/jni/android_os_FileUtils.cpp
@@ -33,46 +33,6 @@
namespace android {
-jint android_os_FileUtils_setPermissions(JNIEnv* env, jobject clazz,
- jstring file, jint mode,
- jint uid, jint gid)
-{
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (uid >= 0 || gid >= 0) {
- int res = chown(file8.string(), uid, gid);
- if (res != 0) {
- return errno;
- }
- }
- return chmod(file8.string(), mode) == 0 ? 0 : errno;
-}
-
-jint android_os_FileUtils_getUid(JNIEnv* env, jobject clazz, jstring file)
-{
- struct stat stats;
- const jchar* str = env->GetStringCritical(file, 0);
- String8 file8;
- if (str) {
- file8 = String8(str, env->GetStringLength(file));
- env->ReleaseStringCritical(file, str);
- }
- if (file8.size() <= 0) {
- return ENOENT;
- }
- if (stat(file8.string(), &stats) < 0) {
- return -1;
- }
- return stats.st_uid;
-}
-
jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring path)
{
if (path == NULL) {
@@ -95,8 +55,6 @@ jint android_os_FileUtils_getFatVolumeId(JNIEnv* env, jobject clazz, jstring pat
}
static const JNINativeMethod methods[] = {
- {"setPermissions", "(Ljava/lang/String;III)I", (void*)android_os_FileUtils_setPermissions},
- {"getUid", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getUid},
{"getFatVolumeId", "(Ljava/lang/String;)I", (void*)android_os_FileUtils_getFatVolumeId},
};
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index e5e3a2f..19f56cd 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -333,6 +333,12 @@ static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
return javaObjectForIBinder(env, token);
}
+static void nativeDestroyDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+ sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+ if (token == NULL) return;
+ SurfaceComposerClient::destroyDisplay(token);
+}
+
static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
jobject tokenObj, jint nativeSurfaceObject) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
@@ -441,6 +447,8 @@ static JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeGetBuiltInDisplay },
{"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
(void*)nativeCreateDisplay },
+ {"nativeDestroyDisplay", "(Landroid/os/IBinder;)V",
+ (void*)nativeDestroyDisplay },
{"nativeSetDisplaySurface", "(Landroid/os/IBinder;I)V",
(void*)nativeSetDisplaySurface },
{"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
diff --git a/core/res/res/drawable-hdpi/stat_sys_adb_am.png b/core/res/res/drawable-hdpi/stat_sys_adb_am.png
index cfbbd8d..0c13339 100644
--- a/core/res/res/drawable-hdpi/stat_sys_adb_am.png
+++ b/core/res/res/drawable-hdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/stat_sys_adb_am.png b/core/res/res/drawable-mdpi/stat_sys_adb_am.png
index 4862919..f0a5089 100644
--- a/core/res/res/drawable-mdpi/stat_sys_adb_am.png
+++ b/core/res/res/drawable-mdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo.png b/core/res/res/drawable-nodpi/platlogo.png
index 63b53b8..4fd0e3c 100644
--- a/core/res/res/drawable-nodpi/platlogo.png
+++ b/core/res/res/drawable-nodpi/platlogo.png
Binary files differ
diff --git a/core/res/res/drawable-nodpi/platlogo_alt.png b/core/res/res/drawable-nodpi/platlogo_alt.png
deleted file mode 100644
index f46c6c6..0000000
--- a/core/res/res/drawable-nodpi/platlogo_alt.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/stat_sys_adb_am.png b/core/res/res/drawable-xhdpi/stat_sys_adb_am.png
index 576ae24..789a3f5 100644
--- a/core/res/res/drawable-xhdpi/stat_sys_adb_am.png
+++ b/core/res/res/drawable-xhdpi/stat_sys_adb_am.png
Binary files differ
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b9840e2..0908f36 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -26,7 +26,7 @@
<item><xliff:g id="id">ime</xliff:g></item>
<item><xliff:g id="id">sync_failing</xliff:g></item>
<item><xliff:g id="id">sync_active</xliff:g></item>
- <item><xliff:g id="id">gps</xliff:g></item>
+ <item><xliff:g id="id">location</xliff:g></item>
<item><xliff:g id="id">bluetooth</xliff:g></item>
<item><xliff:g id="id">nfc</xliff:g></item>
<item><xliff:g id="id">tty</xliff:g></item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 0bfed1b..04cdac9 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -985,7 +985,6 @@
<java-symbol type="drawable" name="jog_tab_target_gray" />
<java-symbol type="drawable" name="picture_emergency" />
<java-symbol type="drawable" name="platlogo" />
- <java-symbol type="drawable" name="platlogo_alt" />
<java-symbol type="drawable" name="stat_notify_sync_error" />
<java-symbol type="drawable" name="stat_notify_wifi_in_range" />
<java-symbol type="drawable" name="stat_notify_rssi_in_range" />
diff --git a/docs/html/guide/topics/providers/content-provider-creating.jd b/docs/html/guide/topics/providers/content-provider-creating.jd
index ebd7c25..6ec1e1b 100644
--- a/docs/html/guide/topics/providers/content-provider-creating.jd
+++ b/docs/html/guide/topics/providers/content-provider-creating.jd
@@ -680,7 +680,7 @@ public class ExampleProvider extends ContentProvider
* Notice that the database itself isn't created or opened
* until SQLiteOpenHelper.getWritableDatabase is called
*/
- mOpenHelper = new SQLiteOpenHelper(
+ mOpenHelper = new MainDatabaseHelper(
getContext(), // the application context
DBNAME, // the name of the database)
null, // uses the default SQLite cursor
diff --git a/docs/html/guide/topics/ui/notifiers/notifications.jd b/docs/html/guide/topics/ui/notifiers/notifications.jd
index e0c87d7..3b1292e 100644
--- a/docs/html/guide/topics/ui/notifiers/notifications.jd
+++ b/docs/html/guide/topics/ui/notifiers/notifications.jd
@@ -285,7 +285,7 @@ page.title=Notifications
<p>
Starting an {@link android.app.Activity} when the user clicks the notification is the most
common action scenario. You can also start an {@link android.app.Activity} when the user
- dismisses an {@link android.app.Activity}. In Android 4.1 and later, you can start an
+ dismisses a notification. In Android 4.1 and later, you can start an
{@link android.app.Activity} from an action button. To learn more, read the reference guide for
{@link android.support.v4.app.NotificationCompat.Builder}.
</p>
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index fdec22b..0ea4074 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -114,9 +114,13 @@ public class Canvas {
* canvas.
*/
public Canvas() {
- // 0 means no native bitmap
- mNativeCanvas = initRaster(0);
- mFinalizer = new CanvasFinalizer(mNativeCanvas);
+ if (!isHardwareAccelerated()) {
+ // 0 means no native bitmap
+ mNativeCanvas = initRaster(0);
+ mFinalizer = new CanvasFinalizer(mNativeCanvas);
+ } else {
+ mFinalizer = null;
+ }
}
/**
@@ -1646,7 +1650,9 @@ public class Canvas {
*/
public void drawPicture(Picture picture) {
picture.endRecording();
- native_drawPicture(mNativeCanvas, picture.ni());
+ int restoreCount = save();
+ picture.draw(this);
+ restoreToCount(restoreCount);
}
/**
@@ -1831,7 +1837,5 @@ public class Canvas {
float hOffset,
float vOffset,
int flags, int paint);
- private static native void native_drawPicture(int nativeCanvas,
- int nativePicture);
private static native void finalizer(int nativeCanvas);
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 331cf6e..69d9916 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -431,6 +431,8 @@ public class Paint {
mRasterizer = paint.mRasterizer;
if (paint.mShader != null) {
mShader = paint.mShader.copy();
+ } else {
+ mShader = null;
}
mTypeface = paint.mTypeface;
mXfermode = paint.mXfermode;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d1bae1e..707f662 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1112,8 +1112,6 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) {
setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) {
@@ -1256,8 +1254,6 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
GL_UNSIGNED_SHORT, NULL));
}
- finishDrawTexture();
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRects(layer->region);
#endif
@@ -2021,9 +2017,6 @@ void OpenGLRenderer::setupDrawIndexedVertices(GLvoid* vertices) {
mCaches.bindPositionVertexPointer(force, vertices, gVertexStride);
}
-void OpenGLRenderer::finishDrawTexture() {
-}
-
///////////////////////////////////////////////////////////////////////////////
// Drawing
///////////////////////////////////////////////////////////////////////////////
@@ -2308,8 +2301,6 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
glDrawArrays(GL_TRIANGLES, 0, count);
- finishDrawTexture();
-
int slot = mCaches.currentProgram->getAttrib("colors");
if (slot >= 0) {
glDisableVertexAttribArray(slot);
@@ -3134,8 +3125,6 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
mesh += (drawCount / 6) * 4;
}
- finishDrawTexture();
-
#if DEBUG_LAYERS_AS_REGIONS
drawRegionRects(layer->region);
#endif
@@ -3270,8 +3259,6 @@ void OpenGLRenderer::drawPathTexture(const PathTexture* texture,
setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
- finishDrawTexture();
}
// Same values used by Skia
@@ -3488,8 +3475,6 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
setupDrawMesh(vertices, texCoords, vbo);
glDrawArrays(drawMode, 0, elementsCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right, float bottom,
@@ -3515,8 +3500,6 @@ void OpenGLRenderer::drawIndexedTextureMesh(float left, float top, float right,
setupDrawMeshIndices(vertices, texCoords, vbo);
glDrawElements(drawMode, elementsCount, GL_UNSIGNED_SHORT, NULL);
-
- finishDrawTexture();
}
void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
@@ -3546,8 +3529,6 @@ void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, f
setupDrawMesh(vertices, texCoords);
glDrawArrays(drawMode, 0, elementsCount);
-
- finishDrawTexture();
}
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 2f8a2f0..1c3bfdc 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -1003,7 +1003,6 @@ private:
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors);
void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0);
void setupDrawIndexedVertices(GLvoid* vertices);
- void finishDrawTexture();
void accountForClear(SkXfermode::Mode mode);
bool updateLayer(Layer* layer, bool inFrame);
diff --git a/location/java/android/location/FusedBatchOptions.aidl b/location/java/android/location/FusedBatchOptions.aidl
new file mode 100644
index 0000000..94cb6e1
--- /dev/null
+++ b/location/java/android/location/FusedBatchOptions.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.location;
+
+parcelable FusedBatchOptions; \ No newline at end of file
diff --git a/location/java/android/location/FusedBatchOptions.java b/location/java/android/location/FusedBatchOptions.java
new file mode 100644
index 0000000..623d707
--- /dev/null
+++ b/location/java/android/location/FusedBatchOptions.java
@@ -0,0 +1,135 @@
+/*
+ * 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.location;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A data class representing a set of options to configure batching sessions.
+ * @hide
+ */
+public class FusedBatchOptions implements Parcelable {
+ private volatile long mPeriodInNS = 0;
+ private volatile int mSourcesToUse = 0;
+ private volatile int mFlags = 0;
+
+ // the default value is set to request fixes at no cost
+ private volatile double mMaxPowerAllocationInMW = 0;
+
+ /*
+ * Getters and setters for properties needed to hold the options.
+ */
+ public void setMaxPowerAllocationInMW(double value) {
+ mMaxPowerAllocationInMW = value;
+ }
+
+ public double getMaxPowerAllocationInMW() {
+ return mMaxPowerAllocationInMW;
+ }
+
+ public void setPeriodInNS(long value) {
+ mPeriodInNS = value;
+ }
+
+ public long getPeriodInNS() {
+ return mPeriodInNS;
+ }
+
+ public void setSourceToUse(int source) {
+ mSourcesToUse |= source;
+ }
+
+ public void resetSourceToUse(int source) {
+ mSourcesToUse &= ~source;
+ }
+
+ public boolean isSourceToUseSet(int source) {
+ return (mSourcesToUse & source) != 0;
+ }
+
+ public int getSourcesToUse() {
+ return mSourcesToUse;
+ }
+
+ public void setFlag(int flag) {
+ mFlags |= flag;
+ }
+
+ public void resetFlag(int flag) {
+ mFlags &= ~flag;
+ }
+
+ public boolean isFlagSet(int flag) {
+ return (mFlags & flag) != 0;
+ }
+
+ public int getFlags() {
+ return mFlags;
+ }
+
+ /**
+ * Definition of enum flag sets needed by this class.
+ * Such values need to be kept in sync with the ones in fused_location.h
+ */
+ public static final class SourceTechnologies {
+ public static int GNSS = 1<<0;
+ public static int WIFI = 1<<1;
+ public static int SENSORS = 1<<2;
+ public static int CELL = 1<<3;
+ public static int BLUETOOTH = 1<<4;
+ }
+
+ public static final class BatchFlags {
+ public static int WAKEUP_ON_FIFO_FULL = 1<<0;
+ public static int CALLBACK_ON_LOCATION_FIX = 1<<1;
+ }
+
+ /*
+ * Method definitions to support Parcelable operations.
+ */
+ public static final Parcelable.Creator<FusedBatchOptions> CREATOR =
+ new Parcelable.Creator<FusedBatchOptions>() {
+ @Override
+ public FusedBatchOptions createFromParcel(Parcel parcel) {
+ FusedBatchOptions options = new FusedBatchOptions();
+ options.setMaxPowerAllocationInMW(parcel.readDouble());
+ options.setPeriodInNS(parcel.readLong());
+ options.setSourceToUse(parcel.readInt());
+ options.setFlag(parcel.readInt());
+ return options;
+ }
+
+ @Override
+ public FusedBatchOptions[] newArray(int size) {
+ return new FusedBatchOptions[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeDouble(mMaxPowerAllocationInMW);
+ parcel.writeLong(mPeriodInNS);
+ parcel.writeInt(mSourcesToUse);
+ parcel.writeInt(mFlags);
+ }
+}
diff --git a/location/java/android/location/IFusedGeofenceHardware.aidl b/location/java/android/location/IFusedGeofenceHardware.aidl
new file mode 100644
index 0000000..9dbf1f4
--- /dev/null
+++ b/location/java/android/location/IFusedGeofenceHardware.aidl
@@ -0,0 +1,93 @@
+/*
+ * 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/license/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.location;
+
+import android.location.Geofence;
+
+/**
+ * Fused Geofence Hardware interface.
+ *
+ * <p>This interface is the basic set of supported functionality by Fused Hardware modules that offer
+ * Geofencing capabilities.
+ *
+ * All operations are asynchronous and the status codes can be obtained via a set of callbacks.
+ *
+ * @hide
+ */
+interface IFusedGeofenceHardware {
+ /**
+ * Flags if the interface functionality is supported by the platform.
+ *
+ * @return true if the functionality is supported, false otherwise.
+ */
+ boolean isSupported();
+
+ /**
+ * Adds a given list of geofences to the system.
+ *
+ * @param geofenceIdsArray The list of geofence Ids to add.
+ * @param geofencesArray the list of geofences to add.
+ */
+ // TODO: [GeofenceIntegration] GeofenceHardwareRequest is not a parcelable class exposed in aidl
+ void addGeofences(in int[] geofenceIdsArray, in Geofence[] geofencesArray);
+
+ /**
+ * Removes a give list of geofences from the system.
+ *
+ * @param geofences The list of geofences to remove.
+ */
+ void removeGeofences(in int[] geofenceIds);
+
+ /**
+ * Pauses monitoring a particular geofence.
+ *
+ * @param geofenceId The geofence to pause monitoring.
+ */
+ void pauseMonitoringGeofence(in int geofenceId);
+
+ /**
+ * Resumes monitoring a particular geofence.
+ *
+ * @param geofenceid The geofence to resume monitoring.
+ * @param transitionsToMonitor The transitions to monitor upon resume.
+ *
+ * Remarks: keep naming of geofence request options consistent with the naming used in
+ * GeofenceHardwareRequest
+ */
+ void resumeMonitoringGeofence(in int geofenceId, in int monitorTransitions);
+
+ /**
+ * Modifies the request options if a geofence that is already known by the
+ * system.
+ *
+ * @param geofenceId The geofence to modify.
+ * @param lastTransition The last known transition state of
+ * the geofence.
+ * @param monitorTransitions The set of transitions to monitor.
+ * @param notificationResponsiveness The notification responsivness needed.
+ * @param unknownTimer The time span associated with the
+ *
+ * Remarks: keep the options as separate fields to be able to leverage the class
+ * GeofenceHardwareRequest without any changes
+ */
+ void modifyGeofenceOptions(
+ in int geofenceId,
+ in int lastTransition,
+ in int monitorTransitions,
+ in int notificationResponsiveness,
+ in int unknownTimer);
+}
diff --git a/location/java/android/location/IFusedProvider.aidl b/location/java/android/location/IFusedProvider.aidl
new file mode 100644
index 0000000..8870d2a
--- /dev/null
+++ b/location/java/android/location/IFusedProvider.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.location;
+
+import android.hardware.location.IFusedLocationHardware;
+
+/**
+ * Interface definition for Location providers that require FLP services.
+ * @hide
+ */
+interface IFusedProvider {
+ /**
+ * Provides access to a FusedLocationHardware instance needed for the provider to work.
+ *
+ * @param instance The FusedLocationHardware available for the provider to use.
+ */
+ void onFusedLocationHardwareChange(in IFusedLocationHardware instance);
+} \ No newline at end of file
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 989178a..e5f1cf5 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -177,6 +177,17 @@ public class LocationManager {
*/
public static final String EXTRA_GPS_ENABLED = "enabled";
+ /**
+ * Broadcast intent action indicating that a high power location requests
+ * has either started or stopped being active. The current state of
+ * active location requests should be read from AppOpsManager using
+ * {@code OP_MONITOR_HIGH_POWER_LOCATION}.
+ *
+ * @hide
+ */
+ public static final String HIGH_POWER_REQUEST_CHANGE_ACTION =
+ "android.location.HIGH_POWER_REQUEST_CHANGE";
+
// Map from LocationListeners to their associated ListenerTransport objects
private HashMap<LocationListener,ListenerTransport> mListeners =
new HashMap<LocationListener,ListenerTransport>();
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardware.java b/location/lib/java/com/android/location/provider/FusedLocationHardware.java
new file mode 100644
index 0000000..abea9fb
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/FusedLocationHardware.java
@@ -0,0 +1,202 @@
+/*
+ * 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 CONDITIOS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.location.provider;
+
+import android.hardware.location.IFusedLocationHardware;
+import android.hardware.location.IFusedLocationHardwareSink;
+
+import android.location.Location;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Class that exposes IFusedLocationHardware functionality to unbundled services.
+ * Namely this is used by GmsCore Fused Location Provider.
+ */
+public final class FusedLocationHardware {
+ private final String TAG = "FusedLocationHardware";
+
+ private IFusedLocationHardware mLocationHardware;
+ ArrayList<FusedLocationHardwareSink> mSinkList = new ArrayList<FusedLocationHardwareSink>();
+
+ private IFusedLocationHardwareSink mInternalSink = new IFusedLocationHardwareSink.Stub() {
+ @Override
+ public void onLocationAvailable(Location[] locations) {
+ dispatchLocations(locations);
+ }
+
+ @Override
+ public void onDiagnosticDataAvailable(String data) {
+ dispatchDiagnosticData(data);
+ }
+ };
+
+ public FusedLocationHardware(IFusedLocationHardware locationHardware) {
+ mLocationHardware = locationHardware;
+ }
+
+ /*
+ * Methods to provide a Facade for IFusedLocationHardware
+ */
+ public void registerSink(FusedLocationHardwareSink sink) {
+ if(sink == null) {
+ return;
+ }
+
+ boolean registerSink = false;
+ synchronized (mSinkList) {
+ // register only on first insertion
+ registerSink = mSinkList.size() == 0;
+ // guarantee uniqueness
+ if(!mSinkList.contains(sink)) {
+ mSinkList.add(sink);
+ }
+ }
+
+ if(registerSink) {
+ try {
+ mLocationHardware.registerSink(mInternalSink);
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at registerSink");
+ }
+ }
+ }
+
+ public void unregisterSink(FusedLocationHardwareSink sink) {
+ if(sink == null) {
+ return;
+ }
+
+ boolean unregisterSink = false;
+ synchronized(mSinkList) {
+ mSinkList.remove(sink);
+ // unregister after the last sink
+ unregisterSink = mSinkList.size() == 0;
+ }
+
+ if(unregisterSink) {
+ try {
+ mLocationHardware.unregisterSink(mInternalSink);
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at unregisterSink");
+ }
+ }
+ }
+
+ public int getSupportedBatchSize() {
+ try {
+ return mLocationHardware.getSupportedBatchSize();
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at getSupportedBatchSize");
+ return 0;
+ }
+ }
+
+ public void startBatching(int id, GmsFusedBatchOptions batchOptions) {
+ try {
+ mLocationHardware.startBatching(id, batchOptions.getParcelableOptions());
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at startBatching");
+ }
+ }
+
+ public void stopBatching(int id) {
+ try {
+ mLocationHardware.stopBatching(id);
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at stopBatching");
+ }
+ }
+
+ public void updateBatchingOptions(int id, GmsFusedBatchOptions batchOptions) {
+ try {
+ mLocationHardware.updateBatchingOptions(id, batchOptions.getParcelableOptions());
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at updateBatchingOptions");
+ }
+ }
+
+ public void requestBatchOfLocations(int batchSizeRequest) {
+ try {
+ mLocationHardware.requestBatchOfLocations(batchSizeRequest);
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at requestBatchOfLocations");
+ }
+ }
+
+ public boolean supportsDiagnosticDataInjection() {
+ try {
+ return mLocationHardware.supportsDiagnosticDataInjection();
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at supportsDiagnisticDataInjection");
+ return false;
+ }
+ }
+
+ public void injectDiagnosticData(String data) {
+ try {
+ mLocationHardware.injectDiagnosticData(data);
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at injectDiagnosticData");
+ }
+ }
+
+ public boolean supportsDeviceContextInjection() {
+ try {
+ return mLocationHardware.supportsDeviceContextInjection();
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at supportsDeviceContextInjection");
+ return false;
+ }
+ }
+
+ public void injectDeviceContext(int deviceEnabledContext) {
+ try {
+ mLocationHardware.injectDeviceContext(deviceEnabledContext);
+ } catch(RemoteException e) {
+ Log.e(TAG, "RemoteException at injectDeviceContext");
+ }
+ }
+
+ /*
+ * Helper methods
+ */
+ private void dispatchLocations(Location[] locations) {
+ ArrayList<FusedLocationHardwareSink> sinks = null;
+ synchronized (mSinkList) {
+ sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
+ }
+
+ for(FusedLocationHardwareSink sink : sinks) {
+ sink.onLocationAvailable(locations);
+ }
+ }
+
+ private void dispatchDiagnosticData(String data) {
+ ArrayList<FusedLocationHardwareSink> sinks = null;
+ synchronized(mSinkList) {
+ sinks = new ArrayList<FusedLocationHardwareSink>(mSinkList);
+ }
+
+ for(FusedLocationHardwareSink sink : sinks) {
+ sink.onDiagnosticDataAvailable(data);
+ }
+ }
+}
diff --git a/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
new file mode 100644
index 0000000..118b663
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/FusedLocationHardwareSink.java
@@ -0,0 +1,31 @@
+/*
+ * 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 com.android.location.provider;
+
+import android.location.Location;
+
+/**
+ * Base class for sinks to interact with FusedLocationHardware.
+ * This is mainly used by GmsCore Fused Provider.
+ */
+public abstract class FusedLocationHardwareSink {
+ /*
+ * Methods to provide a facade for IFusedLocationHardware
+ */
+ public abstract void onLocationAvailable(Location[] locations);
+ public abstract void onDiagnosticDataAvailable(String data);
+} \ No newline at end of file
diff --git a/location/lib/java/com/android/location/provider/FusedProvider.java b/location/lib/java/com/android/location/provider/FusedProvider.java
new file mode 100644
index 0000000..bc9feef
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/FusedProvider.java
@@ -0,0 +1,59 @@
+/*
+ * 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 com.android.location.provider;
+
+import android.hardware.location.IFusedLocationHardware;
+import android.location.IFusedProvider;
+import android.os.IBinder;
+
+/**
+ * Base class for Fused providers implemented as unbundled services.
+ *
+ * <p>Fused providers can be implemented as services and return the result of
+ * {@link com.android.location.provider.FusedProvider#getBinder()} in its getBinder() method.
+ *
+ * <p>IMPORTANT: This class is effectively a public API for unbundled applications, and must remain
+ * API stable. See README.txt in the root of this package for more information.
+ *
+ * @hide
+ */
+public abstract class FusedProvider {
+ private IFusedProvider.Stub mProvider = new IFusedProvider.Stub() {
+ @Override
+ public void onFusedLocationHardwareChange(IFusedLocationHardware instance) {
+ setFusedLocationHardware(new FusedLocationHardware(instance));
+ }
+ };
+
+ /**
+ * Gets the Binder associated with the provider.
+ * This is intended to be used for the onBind() method of a service that implements a fused
+ * service.
+ *
+ * @return The IBinder instance associated with the provider.
+ */
+ public IBinder getBinder() {
+ return mProvider;
+ }
+
+ /**
+ * Sets the FusedLocationHardware instance in the provider..
+ * @param value The instance to set. This can be null in cases where the service connection
+ * is disconnected.
+ */
+ public abstract void setFusedLocationHardware(FusedLocationHardware value);
+}
diff --git a/location/lib/java/com/android/location/provider/GmsFusedBatchOptions.java b/location/lib/java/com/android/location/provider/GmsFusedBatchOptions.java
new file mode 100644
index 0000000..fd3f402
--- /dev/null
+++ b/location/lib/java/com/android/location/provider/GmsFusedBatchOptions.java
@@ -0,0 +1,106 @@
+/*
+ * 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 com.android.location.provider;
+
+import android.location.FusedBatchOptions;
+
+/**
+ * Class that exposes FusedBatchOptions to the GmsCore .
+ */
+public class GmsFusedBatchOptions {
+ private FusedBatchOptions mOptions = new FusedBatchOptions();
+
+ /*
+ * Methods that provide a facade for properties in FusedBatchOptions.
+ */
+ public void setMaxPowerAllocationInMW(double value) {
+ mOptions.setMaxPowerAllocationInMW(value);
+ }
+
+ public double getMaxPowerAllocationInMW() {
+ return mOptions.getMaxPowerAllocationInMW();
+ }
+
+ public void setPeriodInNS(long value) {
+ mOptions.setPeriodInNS(value);
+ }
+
+ public long getPeriodInNS() {
+ return mOptions.getPeriodInNS();
+ }
+
+ public void setSourceToUse(int source) {
+ mOptions.setSourceToUse(source);
+ }
+
+ public void resetSourceToUse(int source) {
+ mOptions.resetSourceToUse(source);
+ }
+
+ public boolean isSourceToUseSet(int source) {
+ return mOptions.isSourceToUseSet(source);
+ }
+
+ public int getSourcesToUse() {
+ return mOptions.getSourcesToUse();
+ }
+
+ public void setFlag(int flag) {
+ mOptions.setFlag(flag);
+ }
+
+ public void resetFlag(int flag) {
+ mOptions.resetFlag(flag);
+ }
+
+ public boolean isFlagSet(int flag) {
+ return mOptions.isFlagSet(flag);
+ }
+
+ public int getFlags() {
+ return mOptions.getFlags();
+ }
+
+ /**
+ * Definition of enum flag sets needed by this class.
+ * Such values need to be kept in sync with the ones in fused_location.h
+ */
+
+ public static final class SourceTechnologies {
+ public static int GNSS = 1<<0;
+ public static int WIFI = 1<<1;
+ public static int SENSORS = 1<<2;
+ public static int CELL = 1<<3;
+ public static int BLUETOOTH = 1<<4;
+ }
+
+ public static final class BatchFlags {
+ public static int WAKEUP_ON_FIFO_FULL = 1<<0;
+ public static int CALLBACK_ON_LOCATION_FIX = 1<<1;
+ }
+
+ /*
+ * Method definitions for internal use.
+ */
+
+ /*
+ * @hide
+ */
+ public FusedBatchOptions getParcelableOptions() {
+ return mOptions;
+ }
+}
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java
index 632334b..cf1238a 100644..100755
--- a/media/java/android/mtp/MtpDatabase.java
+++ b/media/java/android/mtp/MtpDatabase.java
@@ -221,7 +221,7 @@ public class MtpDatabase {
if (c != null) c.close();
if (db != null) db.close();
}
- databaseFile.delete();
+ context.deleteDatabase(devicePropertiesName);
}
}
diff --git a/media/mca/filterfw/native/core/gl_env.cpp b/media/mca/filterfw/native/core/gl_env.cpp
index fdecda3..84dad8c 100644
--- a/media/mca/filterfw/native/core/gl_env.cpp
+++ b/media/mca/filterfw/native/core/gl_env.cpp
@@ -26,6 +26,8 @@
#include <string>
#include <EGL/eglext.h>
+#include <gui/GLConsumer.h>
+
namespace android {
namespace filterfw {
diff --git a/media/mca/filterfw/native/core/gl_env.h b/media/mca/filterfw/native/core/gl_env.h
index 81e1e9d..a709638 100644
--- a/media/mca/filterfw/native/core/gl_env.h
+++ b/media/mca/filterfw/native/core/gl_env.h
@@ -31,6 +31,9 @@
#include <gui/Surface.h>
namespace android {
+
+class GLConsumer;
+
namespace filterfw {
class ShaderProgram;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 8e7e087..a536acb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -72,7 +72,7 @@ public class DocumentsActivity extends Activity {
private final DisplayState mDisplayState = new DisplayState();
/** Current user navigation stack; empty implies recents. */
- private DocumentStack mStack;
+ private DocumentStack mStack = new DocumentStack();
/** Currently active search, overriding any stack. */
private String mCurrentSearch;
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2629b11..5e198a2 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -24,6 +24,7 @@
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
+ <uses-permission android:name="android.permission.GET_APP_OPS_STATS" />
<!-- Networking and telephony -->
<uses-permission android:name="android.permission.BLUETOOTH" />
@@ -188,37 +189,6 @@
android:taskAffinity="com.android.systemui.net"
android:excludeFromRecents="true" />
- <!-- started from ... somewhere -->
- <activity
- android:name=".BeanBag"
- android:exported="true"
- android:label="BeanBag"
- android:icon="@drawable/redbean2"
- android:theme="@android:style/Theme.Wallpaper.NoTitleBar.Fullscreen"
- android:hardwareAccelerated="true"
- android:launchMode="singleInstance"
- android:excludeFromRecents="true">
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="android.intent.category.DEFAULT" />
- <category android:name="com.android.internal.category.PLATLOGO" />
-<!-- <category android:name="android.intent.category.LAUNCHER" />-->
- </intent-filter>
- </activity>
-
- <!-- Beans in space -->
- <service
- android:name=".BeanBagDream"
- android:exported="true"
- android:label="@string/jelly_bean_dream_name"
- android:enabled="false"
- >
- <intent-filter>
- <action android:name="android.service.dreams.DreamService" />
- <category android:name="android.intent.category.DEFAULT" />
- </intent-filter>
- </service>
-
<activity android:name=".Somnambulator"
android:label="@string/start_dreams"
android:icon="@mipmap/ic_launcher_dreams"
diff --git a/packages/SystemUI/res/drawable-hdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-hdpi/heads_up_window_bg.9.png
new file mode 100644
index 0000000..3b952d0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/heads_up_window_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
new file mode 100644
index 0000000..657a612
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/heads_up_window_bg.9.png b/packages/SystemUI/res/drawable-mdpi/heads_up_window_bg.9.png
new file mode 100644
index 0000000..a0ab991
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/heads_up_window_bg.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
new file mode 100644
index 0000000..80fc24b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/qs_coming_soon.png b/packages/SystemUI/res/drawable-nodpi/qs_coming_soon.png
deleted file mode 100644
index 47c89b1..0000000
--- a/packages/SystemUI/res/drawable-nodpi/qs_coming_soon.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/redbean0.png b/packages/SystemUI/res/drawable-nodpi/redbean0.png
deleted file mode 100644
index b088939..0000000
--- a/packages/SystemUI/res/drawable-nodpi/redbean0.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/redbean1.png b/packages/SystemUI/res/drawable-nodpi/redbean1.png
deleted file mode 100644
index 8fc8d9d..0000000
--- a/packages/SystemUI/res/drawable-nodpi/redbean1.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/redbean2.png b/packages/SystemUI/res/drawable-nodpi/redbean2.png
deleted file mode 100644
index ef11ca8..0000000
--- a/packages/SystemUI/res/drawable-nodpi/redbean2.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/redbeandroid.png b/packages/SystemUI/res/drawable-nodpi/redbeandroid.png
deleted file mode 100644
index 9aa3f82..0000000
--- a/packages/SystemUI/res/drawable-nodpi/redbeandroid.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
new file mode 100644
index 0000000..fd8ad64
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_device_access_location_found.png
Binary files differ
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0073e60..33a85c3 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -418,6 +418,9 @@
<!-- Notification text: when GPS has found a fix [CHAR LIMIT=50] -->
<string name="gps_notification_found_text">Location set by GPS</string>
+ <!-- Accessibility text describing the presence of active location requests by one or more apps -->
+ <string name="accessibility_location_active">Location requests active</string>
+
<!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_clear_all">Clear all notifications.</string>
diff --git a/packages/SystemUI/src/com/android/systemui/BeanBag.java b/packages/SystemUI/src/com/android/systemui/BeanBag.java
deleted file mode 100644
index a396759..0000000
--- a/packages/SystemUI/src/com/android/systemui/BeanBag.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*);
- * Copyright (C) 2012 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 com.android.systemui;
-
-import android.animation.TimeAnimator;
-import android.app.Activity;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
-import android.graphics.drawable.BitmapDrawable;
-import android.util.AttributeSet;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-
-import java.util.Random;
-
-public class BeanBag extends Activity {
- final static boolean DEBUG = false;
-
- public static class Board extends FrameLayout
- {
- static Random sRNG = new Random();
-
- static float lerp(float a, float b, float f) {
- return (b-a)*f + a;
- }
-
- static float randfrange(float a, float b) {
- return lerp(a, b, sRNG.nextFloat());
- }
-
- static int randsign() {
- return sRNG.nextBoolean() ? 1 : -1;
- }
-
- static boolean flip() {
- return sRNG.nextBoolean();
- }
-
- static float mag(float x, float y) {
- return (float) Math.sqrt(x*x+y*y);
- }
-
- static float clamp(float x, float a, float b) {
- return ((x<a)?a:((x>b)?b:x));
- }
-
- static float dot(float x1, float y1, float x2, float y2) {
- return x1*x2+y1+y2;
- }
-
- static <E> E pick(E[] array) {
- if (array.length == 0) return null;
- return array[sRNG.nextInt(array.length)];
- }
-
- static int pickInt(int[] array) {
- if (array.length == 0) return 0;
- return array[sRNG.nextInt(array.length)];
- }
-
- static int NUM_BEANS = 40;
- static float MIN_SCALE = 0.2f;
- static float MAX_SCALE = 1f;
-
- static float LUCKY = 0.001f;
-
- static int MAX_RADIUS = (int)(576 * MAX_SCALE);
-
- static int BEANS[] = {
- R.drawable.redbean0,
- R.drawable.redbean0,
- R.drawable.redbean0,
- R.drawable.redbean0,
- R.drawable.redbean1,
- R.drawable.redbean1,
- R.drawable.redbean2,
- R.drawable.redbean2,
- R.drawable.redbeandroid,
- };
-
- static int COLORS[] = {
- 0xFF00CC00,
- 0xFFCC0000,
- 0xFF0000CC,
- 0xFFFFFF00,
- 0xFFFF8000,
- 0xFF00CCFF,
- 0xFFFF0080,
- 0xFF8000FF,
- 0xFFFF8080,
- 0xFF8080FF,
- 0xFFB0C0D0,
- 0xFFDDDDDD,
- 0xFF333333,
- };
-
- public class Bean extends ImageView {
- public static final float VMAX = 1000.0f;
- public static final float VMIN = 100.0f;
-
- public float x, y, a;
-
- public float va;
- public float vx, vy;
-
- public float r;
-
- public float z;
-
- public int h,w;
-
- public boolean grabbed;
- public float grabx, graby;
- public long grabtime;
- private float grabx_offset, graby_offset;
-
- public Bean(Context context, AttributeSet as) {
- super(context, as);
- }
-
- public String toString() {
- return String.format("<bean (%.1f, %.1f) (%d x %d)>",
- getX(), getY(), getWidth(), getHeight());
- }
-
- private void pickBean() {
- int beanId = pickInt(BEANS);
- if (randfrange(0,1) <= LUCKY) {
- beanId = R.drawable.jandycane;
- }
- BitmapDrawable bean = (BitmapDrawable) getContext().getResources().getDrawable(beanId);
- Bitmap beanBits = bean.getBitmap();
- h=beanBits.getHeight();
- w=beanBits.getWidth();
-
- if (DEBUG) {
- bean.setAlpha(0x80);
- }
- this.setImageDrawable(bean);
-
- Paint pt = new Paint();
- final int color = pickInt(COLORS);
- ColorMatrix CM = new ColorMatrix();
- float[] M = CM.getArray();
- // we assume the color information is in the red channel
- /* R */ M[0] = (float)((color & 0x00FF0000) >> 16) / 0xFF;
- /* G */ M[5] = (float)((color & 0x0000FF00) >> 8) / 0xFF;
- /* B */ M[10] = (float)((color & 0x000000FF)) / 0xFF;
- pt.setColorFilter(new ColorMatrixColorFilter(M));
- setLayerType(View.LAYER_TYPE_HARDWARE, (beanId == R.drawable.jandycane) ? null : pt);
- }
-
- public void reset() {
- pickBean();
-
- final float scale = lerp(MIN_SCALE,MAX_SCALE,z);
- setScaleX(scale); setScaleY(scale);
-
- r = 0.3f*Math.max(h,w)*scale;
-
- a=(randfrange(0,360));
- va = randfrange(-30,30);
-
- vx = randfrange(-40,40) * z;
- vy = randfrange(-40,40) * z;
- final float boardh = boardHeight;
- final float boardw = boardWidth;
- //android.util.Log.d("BeanBag", "reset: w="+w+" h="+h);
- if (flip()) {
- x=(vx < 0 ? boardw+2*r : -r*4f);
- y=(randfrange(0, boardh-3*r)*0.5f + ((vy < 0)?boardh*0.5f:0));
- } else {
- y=(vy < 0 ? boardh+2*r : -r*4f);
- x=(randfrange(0, boardw-3*r)*0.5f + ((vx < 0)?boardw*0.5f:0));
- }
- }
-
- public void update(float dt) {
- if (grabbed) {
-// final float interval = (SystemClock.uptimeMillis() - grabtime) / 1000f;
- vx = (vx * 0.75f) + ((grabx - x) / dt) * 0.25f;
- x = grabx;
- vy = (vy * 0.75f) + ((graby - y) / dt) * 0.25f;;
- y = graby;
- } else {
- x = (x + vx * dt);
- y = (y + vy * dt);
- a = (a + va * dt);
- }
- }
-
- public float overlap(Bean other) {
- final float dx = (x - other.x);
- final float dy = (y - other.y);
- return mag(dx, dy) - r - other.r;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent e) {
- switch (e.getAction()) {
- case MotionEvent.ACTION_DOWN:
- grabbed = true;
- grabx_offset = e.getRawX() - x;
- graby_offset = e.getRawY() - y;
- va = 0;
- // fall
- case MotionEvent.ACTION_MOVE:
- grabx = e.getRawX() - grabx_offset;
- graby = e.getRawY() - graby_offset;
- grabtime = e.getEventTime();
- break;
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP:
- grabbed = false;
- float a = randsign() * clamp(mag(vx, vy) * 0.33f, 0, 1080f);
- va = randfrange(a*0.5f, a);
- break;
- }
- return true;
- }
- }
-
- TimeAnimator mAnim;
- private int boardWidth;
- private int boardHeight;
-
- public Board(Context context, AttributeSet as) {
- super(context, as);
-
- setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE);
-
- setWillNotDraw(!DEBUG);
- }
-
- private void reset() {
-// android.util.Log.d("Nyandroid", "board reset");
- removeAllViews();
-
- final ViewGroup.LayoutParams wrap = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.WRAP_CONTENT,
- ViewGroup.LayoutParams.WRAP_CONTENT);
-
- for(int i=0; i<NUM_BEANS; i++) {
- Bean nv = new Bean(getContext(), null);
- addView(nv, wrap);
- nv.z = ((float)i/NUM_BEANS);
- nv.z *= nv.z;
- nv.reset();
- nv.x = (randfrange(0, boardWidth));
- nv.y = (randfrange(0, boardHeight));
- }
-
- if (mAnim != null) {
- mAnim.cancel();
- }
- mAnim = new TimeAnimator();
- mAnim.setTimeListener(new TimeAnimator.TimeListener() {
- private long lastPrint = 0;
- public void onTimeUpdate(TimeAnimator animation, long totalTime, long deltaTime) {
- if (DEBUG && totalTime - lastPrint > 5000) {
- lastPrint = totalTime;
- for (int i=0; i<getChildCount(); i++) {
- android.util.Log.d("BeanBag", "bean " + i + ": " + getChildAt(i));
- }
- }
-
- for (int i=0; i<getChildCount(); i++) {
- View v = getChildAt(i);
- if (!(v instanceof Bean)) continue;
- Bean nv = (Bean) v;
- nv.update(deltaTime / 1000f);
-
- for (int j=i+1; j<getChildCount(); j++) {
- View v2 = getChildAt(j);
- if (!(v2 instanceof Bean)) continue;
- Bean nv2 = (Bean) v2;
- final float overlap = nv.overlap(nv2);
- }
-
- nv.setRotation(nv.a);
- nv.setX(nv.x-nv.getPivotX());
- nv.setY(nv.y-nv.getPivotY());
-
- if ( nv.x < - MAX_RADIUS
- || nv.x > boardWidth + MAX_RADIUS
- || nv.y < -MAX_RADIUS
- || nv.y > boardHeight + MAX_RADIUS)
- {
- nv.reset();
- }
- }
-
- if (DEBUG) invalidate();
- }
- });
- }
-
- @Override
- protected void onSizeChanged (int w, int h, int oldw, int oldh) {
- super.onSizeChanged(w,h,oldw,oldh);
- boardWidth = w;
- boardHeight = h;
-// android.util.Log.d("Nyandroid", "resized: " + w + "x" + h);
- }
-
- public void startAnimation() {
- stopAnimation();
- if (mAnim == null) {
- post(new Runnable() { public void run() {
- reset();
- startAnimation();
- } });
- } else {
- mAnim.start();
- }
- }
-
- public void stopAnimation() {
- if (mAnim != null) mAnim.cancel();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- stopAnimation();
- }
-
- @Override
- public boolean isOpaque() {
- return false;
- }
-
- @Override
- public void onDraw(Canvas c) {
- if (DEBUG) {
- //android.util.Log.d("BeanBag", "onDraw");
- Paint pt = new Paint();
- pt.setAntiAlias(true);
- pt.setStyle(Paint.Style.STROKE);
- pt.setColor(0xFFFF0000);
- pt.setStrokeWidth(4.0f);
- c.drawRect(0, 0, getWidth(), getHeight(), pt);
- pt.setColor(0xFFFFCC00);
- pt.setStrokeWidth(1.0f);
- for (int i=0; i<getChildCount(); i++) {
- Bean b = (Bean) getChildAt(i);
- final float a = (360-b.a)/180f*3.14159f;
- final float tx = b.getTranslationX();
- final float ty = b.getTranslationY();
- c.drawCircle(b.x, b.y, b.r, pt);
- c.drawCircle(tx, ty, 4, pt);
- c.drawLine(b.x, b.y, (float)(b.x+b.r*Math.sin(a)), (float)(b.y+b.r*Math.cos(a)), pt);
- }
- }
- }
- }
-
- private Board mBoard;
-
- @Override
- public void onStart() {
- super.onStart();
-
- // ACHIEVEMENT UNLOCKED
- PackageManager pm = getPackageManager();
- pm.setComponentEnabledSetting(new ComponentName(this, BeanBagDream.class),
- PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0);
-
- getWindow().addFlags(
- WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
- | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
- );
- mBoard = new Board(this, null);
- setContentView(mBoard);
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mBoard.stopAnimation();
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mBoard.startAnimation();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/BeanBagDream.java b/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
deleted file mode 100644
index 39e4727..0000000
--- a/packages/SystemUI/src/com/android/systemui/BeanBagDream.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.systemui;
-
-import android.service.dreams.DreamService;
-
-import com.android.systemui.BeanBag.Board;
-
-public class BeanBagDream extends DreamService {
-
- private Board mBoard;
-
- @Override
- public void onAttachedToWindow() {
- super.onAttachedToWindow();
- setInteractive(true);
- setFullscreen(true);
- mBoard = new Board(this, null);
- setContentView(mBoard);
- }
-
- @Override
- public void onDreamingStarted() {
- super.onDreamingStarted();
- mBoard.startAnimation();
- }
-
- @Override
- public void onDreamingStopped() {
- mBoard.stopAnimation();
- super.onDreamingStopped();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index a92703c..c914a34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -129,6 +129,8 @@ public class PhoneStatusBar extends BaseStatusBar {
private static final int STATUS_OR_NAV_TRANSIENT =
View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
+ private static final int TRANSIENT_NAV_HIDING =
+ View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT;
private static final long AUTOHIDE_TIMEOUT_MS = 3000;
private static final float TRANSPARENT_ALPHA = 0.7f;
@@ -1955,14 +1957,12 @@ public class PhoneStatusBar extends BaseStatusBar {
// update hiding navigation confirmation
if (mNavigationBarView != null) {
- final int hidingNav =
- View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_ALLOW_TRANSIENT;
- boolean oldHidingNav = (oldVal & hidingNav) != 0;
- boolean newHidingNav = (newVal & hidingNav) != 0;
- if (!oldHidingNav && newHidingNav) {
+ boolean oldShowConfirm = (oldVal & TRANSIENT_NAV_HIDING) == TRANSIENT_NAV_HIDING;
+ boolean newShowConfirm = (newVal & TRANSIENT_NAV_HIDING) == TRANSIENT_NAV_HIDING;
+ if (!oldShowConfirm && newShowConfirm) {
mHidingNavigationConfirmationDismissed = false;
}
- setHidingNavigationConfirmationVisible(newHidingNav);
+ setHidingNavigationConfirmationVisible(newShowConfirm);
}
// send updated sysui visibility to window manager
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
index 3f8043d..91ddf0f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationController.java
@@ -16,10 +16,8 @@
package com.android.systemui.statusbar.policy;
-import android.app.INotificationManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
+import android.app.AppOpsManager;
+import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -28,36 +26,39 @@ import android.content.IntentFilter;
import android.database.ContentObserver;
import android.location.LocationManager;
import android.os.Handler;
-import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import com.android.systemui.R;
import java.util.ArrayList;
+import java.util.List;
+/**
+ * A controller to manage changes of location related states and update the views accordingly.
+ */
public class LocationController extends BroadcastReceiver {
- private static final String TAG = "StatusBar.LocationController";
+ // The name of the placeholder corresponding to the location request status icon.
+ // This string corresponds to config_statusBarIcons in core/res/res/values/config.xml.
+ private static final String LOCATION_STATUS_ICON_PLACEHOLDER = "location";
+ private static final int LOCATION_STATUS_ICON_ID
+ = R.drawable.stat_sys_device_access_location_found;
- private static final int GPS_NOTIFICATION_ID = 374203-122084;
+ private static final int[] mHighPowerRequestAppOpArray
+ = new int[] {AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION};
private Context mContext;
- private INotificationManager mNotificationService;
+ private AppOpsManager mAppOpsManager;
+ private StatusBarManager mStatusBarManager;
+
+ private boolean mAreActiveLocationRequests;
+ private boolean mIsAirplaneMode;
- private ArrayList<LocationGpsStateChangeCallback> mChangeCallbacks =
- new ArrayList<LocationGpsStateChangeCallback>();
private ArrayList<LocationSettingsChangeCallback> mSettingsChangeCallbacks =
new ArrayList<LocationSettingsChangeCallback>();
/**
- * A callback for change in gps status (enabled/disabled, have lock, etc).
- */
- public interface LocationGpsStateChangeCallback {
- public void onLocationGpsStateChanged(boolean inUse, String description);
- }
-
- /**
* A callback for change in location settings (the user has enabled/disabled location).
*/
public interface LocationSettingsChangeCallback {
@@ -74,13 +75,15 @@ public class LocationController extends BroadcastReceiver {
mContext = context;
IntentFilter filter = new IntentFilter();
- filter.addAction(LocationManager.GPS_ENABLED_CHANGE_ACTION);
- filter.addAction(LocationManager.GPS_FIX_CHANGE_ACTION);
+ filter.addAction(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
+ // Listen for a change in the airplane mode setting so we can defensively turn off the
+ // high power location icon when radios are disabled.
+ filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
context.registerReceiver(this, filter);
- NotificationManager nm = (NotificationManager)context.getSystemService(
- Context.NOTIFICATION_SERVICE);
- mNotificationService = nm.getService();
+ mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+ mStatusBarManager
+ = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
// Register to listen for changes to the location settings
context.getContentResolver().registerContentObserver(
@@ -94,13 +97,11 @@ public class LocationController extends BroadcastReceiver {
}
}
});
- }
- /**
- * Add a callback to listen for changes in gps status.
- */
- public void addStateChangedCallback(LocationGpsStateChangeCallback cb) {
- mChangeCallbacks.add(cb);
+ // Examine the current location state and initialize the status view.
+ updateActiveLocationRequests();
+ updateAirplaneMode();
+ refreshViews();
}
/**
@@ -145,76 +146,77 @@ public class LocationController extends BroadcastReceiver {
return isGpsEnabled || isNetworkEnabled;
}
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- final boolean enabled = intent.getBooleanExtra(LocationManager.EXTRA_GPS_ENABLED, false);
-
- boolean visible;
- int iconId, textResId;
-
- if (action.equals(LocationManager.GPS_FIX_CHANGE_ACTION) && enabled) {
- // GPS is getting fixes
- iconId = com.android.internal.R.drawable.stat_sys_gps_on;
- textResId = R.string.gps_notification_found_text;
- visible = true;
- } else if (action.equals(LocationManager.GPS_ENABLED_CHANGE_ACTION) && !enabled) {
- // GPS is off
- visible = false;
- iconId = textResId = 0;
+ /**
+ * Returns true if there currently exist active high power location requests.
+ */
+ private boolean areActiveHighPowerLocationRequests() {
+ List<AppOpsManager.PackageOps> packages
+ = mAppOpsManager.getPackagesForOps(mHighPowerRequestAppOpArray);
+ // AppOpsManager can return null when there is no requested data.
+ if (packages != null) {
+ final int numPackages = packages.size();
+ for (int packageInd = 0; packageInd < numPackages; packageInd++) {
+ AppOpsManager.PackageOps packageOp = packages.get(packageInd);
+ List<AppOpsManager.OpEntry> opEntries = packageOp.getOps();
+ if (opEntries != null) {
+ final int numOps = opEntries.size();
+ for (int opInd = 0; opInd < numOps; opInd++) {
+ AppOpsManager.OpEntry opEntry = opEntries.get(opInd);
+ // AppOpsManager should only return OP_MONITOR_HIGH_POWER_LOCATION because
+ // of the mHighPowerRequestAppOpArray filter, but checking defensively.
+ if (opEntry.getOp() == AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION) {
+ if (opEntry.isRunning()) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // Updates the status view based on the current state of location requests and airplane mode.
+ private void refreshViews() {
+ // The airplane mode check is defensive - there shouldn't be any active high power
+ // location requests when airplane mode is on.
+ if (!mIsAirplaneMode && mAreActiveLocationRequests) {
+ mStatusBarManager.setIcon(LOCATION_STATUS_ICON_PLACEHOLDER, LOCATION_STATUS_ICON_ID, 0,
+ mContext.getString(R.string.accessibility_location_active));
} else {
- // GPS is on, but not receiving fixes
- iconId = R.drawable.stat_sys_gps_acquiring_anim;
- textResId = R.string.gps_notification_searching_text;
- visible = true;
+ mStatusBarManager.removeIcon(LOCATION_STATUS_ICON_PLACEHOLDER);
}
+ }
- try {
- if (visible) {
- Intent gpsIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
- gpsIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-
- PendingIntent pendingIntent = PendingIntent.getActivityAsUser(context, 0,
- gpsIntent, 0, null, UserHandle.CURRENT);
- String text = mContext.getText(textResId).toString();
-
- Notification n = new Notification.Builder(mContext)
- .setSmallIcon(iconId)
- .setContentTitle(text)
- .setOngoing(true)
- .setContentIntent(pendingIntent)
- .getNotification();
-
- // Notification.Builder will helpfully fill these out for you no matter what you do
- n.tickerView = null;
- n.tickerText = null;
-
- n.priority = Notification.PRIORITY_HIGH;
-
- int[] idOut = new int[1];
- mNotificationService.enqueueNotificationWithTag(
- mContext.getPackageName(), mContext.getBasePackageName(),
- null,
- GPS_NOTIFICATION_ID,
- n,
- idOut,
- UserHandle.USER_ALL);
-
- for (LocationGpsStateChangeCallback cb : mChangeCallbacks) {
- cb.onLocationGpsStateChanged(true, text);
- }
- } else {
- mNotificationService.cancelNotificationWithTag(
- mContext.getPackageName(), null,
- GPS_NOTIFICATION_ID, UserHandle.USER_ALL);
+ // Reads the active location requests and updates the status view if necessary.
+ private void updateActiveLocationRequests() {
+ boolean hadActiveLocationRequests = mAreActiveLocationRequests;
+ mAreActiveLocationRequests = areActiveHighPowerLocationRequests();
+ if (mAreActiveLocationRequests != hadActiveLocationRequests) {
+ refreshViews();
+ }
+ }
- for (LocationGpsStateChangeCallback cb : mChangeCallbacks) {
- cb.onLocationGpsStateChanged(false, null);
- }
- }
- } catch (android.os.RemoteException ex) {
- // well, it was worth a shot
+ // Reads the airplane mode setting and updates the status view if necessary.
+ private void updateAirplaneMode() {
+ boolean wasAirplaneMode = mIsAirplaneMode;
+ // TODO This probably warrants a utility method in Settings.java.
+ mIsAirplaneMode = (Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.AIRPLANE_MODE_ON, 0) == 1);
+ if (mIsAirplaneMode != wasAirplaneMode) {
+ refreshViews();
}
}
-}
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION.equals(action)) {
+ updateActiveLocationRequests();
+ } else if (Intent.ACTION_AIRPLANE_MODE_CHANGED.equals(action)) {
+ updateAirplaneMode();
+ }
+ }
+}
diff --git a/services/java/com/android/server/AppOpsService.java b/services/java/com/android/server/AppOpsService.java
index 81572c5..7af95f3 100644
--- a/services/java/com/android/server/AppOpsService.java
+++ b/services/java/com/android/server/AppOpsService.java
@@ -426,12 +426,14 @@ public class AppOpsService extends IAppOpsService.Stub {
HashMap<Callback, ArrayList<Pair<String, Integer>>> callbacks = null;
synchronized (this) {
boolean changed = false;
- for (int i=0; i<mUidOps.size(); i++) {
+ for (int i=mUidOps.size()-1; i>=0; i--) {
HashMap<String, Ops> packages = mUidOps.valueAt(i);
- for (Map.Entry<String, Ops> ent : packages.entrySet()) {
+ Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, Ops> ent = it.next();
String packageName = ent.getKey();
Ops pkgOps = ent.getValue();
- for (int j=0; j<pkgOps.size(); j++) {
+ for (int j=pkgOps.size()-1; j>=0; j--) {
Op curOp = pkgOps.valueAt(j);
if (curOp.mode != AppOpsManager.MODE_ALLOWED) {
curOp.mode = AppOpsManager.MODE_ALLOWED;
@@ -440,9 +442,17 @@ public class AppOpsService extends IAppOpsService.Stub {
mOpModeWatchers.get(curOp.op));
callbacks = addCallbacks(callbacks, packageName, curOp.op,
mPackageModeWatchers.get(packageName));
- pruneOp(curOp, mUidOps.keyAt(i), packageName);
+ if (curOp.time == 0 && curOp.rejectTime == 0) {
+ pkgOps.removeAt(j);
+ }
}
}
+ if (pkgOps.size() == 0) {
+ it.remove();
+ }
+ }
+ if (packages.size() == 0) {
+ mUidOps.removeAt(i);
}
}
if (changed) {
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 3ae2eb5..bb0d248 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2221,15 +2221,26 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ if (DBG) log("handleCaptivePortalTrackerCheck: call captivePortalCheckComplete ni=" + info);
thisNet.captivePortalCheckComplete();
}
/** @hide */
+ @Override
public void captivePortalCheckComplete(NetworkInfo info) {
enforceConnectivityInternalPermission();
+ if (DBG) log("captivePortalCheckComplete: ni=" + info);
mNetTrackers[info.getType()].captivePortalCheckComplete();
}
+ /** @hide */
+ @Override
+ public void captivePortalCheckCompleted(NetworkInfo info, boolean isCaptivePortal) {
+ enforceConnectivityInternalPermission();
+ if (DBG) log("captivePortalCheckCompleted: ni=" + info + " captive=" + isCaptivePortal);
+ mNetTrackers[info.getType()].captivePortalCheckCompleted(isCaptivePortal);
+ }
+
/**
* Setup data activity tracking for the given network interface.
*
@@ -3916,11 +3927,26 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// hipri connection so the default connection stays active.
log("isMobileOk: start hipri url=" + params.mUrl);
mCs.setEnableFailFastMobileData(DctConstants.ENABLED);
- mCs.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
- Phone.FEATURE_ENABLE_HIPRI, new Binder());
// Continue trying to connect until time has run out
long endTime = SystemClock.elapsedRealtime() + params.mTimeOutMs;
+
+ // First wait until we can start using hipri
+ Binder binder = new Binder();
+ while(SystemClock.elapsedRealtime() < endTime) {
+ int ret = mCs.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
+ Phone.FEATURE_ENABLE_HIPRI, binder);
+ if ((ret == PhoneConstants.APN_ALREADY_ACTIVE)
+ || (ret == PhoneConstants.APN_REQUEST_STARTED)) {
+ log("isMobileOk: hipri started");
+ break;
+ }
+ if (VDBG) log("isMobileOk: hipri not started yet");
+ result = ConnectivityManager.CMP_RESULT_CODE_NO_CONNECTION;
+ sleep(1);
+ }
+
+ // Continue trying to connect until time has run out
while(SystemClock.elapsedRealtime() < endTime) {
try {
// Wait for hipri to connect.
@@ -4272,7 +4298,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return null;
}
- private String getMobileRedirectedProvisioningUrl() {
+ @Override
+ public String getMobileRedirectedProvisioningUrl() {
+ enforceConnectivityInternalPermission();
String url = getProvisioningUrlBaseFromFile(REDIRECTED_PROVISIONING);
if (TextUtils.isEmpty(url)) {
url = mContext.getResources().getString(R.string.mobile_redirected_provisioning_url);
@@ -4280,14 +4308,15 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return url;
}
+ @Override
public String getMobileProvisioningUrl() {
enforceConnectivityInternalPermission();
String url = getProvisioningUrlBaseFromFile(PROVISIONING);
if (TextUtils.isEmpty(url)) {
url = mContext.getResources().getString(R.string.mobile_provisioning_url);
- log("getProvisioningUrl: mobile_provisioining_url from resource =" + url);
+ log("getMobileProvisioningUrl: mobile_provisioining_url from resource =" + url);
} else {
- log("getProvisioningUrl: mobile_provisioning_url from File =" + url);
+ log("getMobileProvisioningUrl: mobile_provisioning_url from File =" + url);
}
// populate the iccid, imei and phone number in the provisioning url.
if (!TextUtils.isEmpty(url)) {
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index 4c81006..43f95c3 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -2378,7 +2378,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public boolean setDeviceOwner(String packageName) {
+ public boolean setDeviceOwner(String packageName, String ownerName) {
if (packageName == null
|| !DeviceOwner.isInstalled(packageName, mContext.getPackageManager())) {
throw new IllegalArgumentException("Invalid package name " + packageName
@@ -2386,7 +2386,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
synchronized (this) {
if (mDeviceOwner == null && !isDeviceProvisioned()) {
- mDeviceOwner = new DeviceOwner(packageName);
+ mDeviceOwner = new DeviceOwner(packageName, ownerName);
mDeviceOwner.writeOwnerFile();
return true;
} else {
@@ -2415,6 +2415,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return null;
}
+ @Override
+ public String getDeviceOwnerName() {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
+ synchronized (this) {
+ if (mDeviceOwner != null) {
+ return mDeviceOwner.getName();
+ }
+ }
+ return null;
+ }
+
private boolean isDeviceProvisioned() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.DEVICE_PROVISIONED, 0) > 0;
@@ -2488,15 +2499,18 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
static class DeviceOwner {
private static final String DEVICE_OWNER_XML = "device_owner.xml";
private static final String TAG_DEVICE_OWNER = "device-owner";
+ private static final String ATTR_NAME = "name";
private static final String ATTR_PACKAGE = "package";
private String mPackageName;
+ private String mOwnerName;
DeviceOwner() {
readOwnerFile();
}
- DeviceOwner(String packageName) {
+ DeviceOwner(String packageName, String ownerName) {
this.mPackageName = packageName;
+ this.mOwnerName = ownerName;
}
static boolean isRegistered() {
@@ -2508,6 +2522,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return mPackageName;
}
+ String getName() {
+ return mOwnerName;
+ }
+
static boolean isInstalled(String packageName, PackageManager pm) {
try {
PackageInfo pi;
@@ -2539,6 +2557,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
"Device Owner file does not start with device-owner tag: found " + tag);
}
mPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
+ mOwnerName = parser.getAttributeValue(null, ATTR_NAME);
input.close();
} catch (XmlPullParserException xppe) {
Slog.e(TAG, "Error parsing device-owner file\n" + xppe);
@@ -2563,6 +2582,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
out.startDocument(null, true);
out.startTag(null, TAG_DEVICE_OWNER);
out.attribute(null, ATTR_PACKAGE, mPackageName);
+ if (mOwnerName != null) {
+ out.attribute(null, ATTR_NAME, mOwnerName);
+ }
out.endTag(null, TAG_DEVICE_OWNER);
out.endDocument();
out.flush();
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index cde84dc..49746ff 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -63,6 +63,8 @@ import com.android.internal.content.PackageMonitor;
import com.android.internal.location.ProviderProperties;
import com.android.internal.location.ProviderRequest;
import com.android.internal.os.BackgroundThread;
+import com.android.server.location.FlpHardwareProvider;
+import com.android.server.location.FusedProxy;
import com.android.server.location.GeocoderProxy;
import com.android.server.location.GeofenceProxy;
import com.android.server.location.GeofenceManager;
@@ -429,6 +431,17 @@ public class LocationManagerService extends ILocationManager.Stub {
Slog.e(TAG, "no geofence provider found");
}
+ // bind to fused provider
+ // TODO: [GeofenceIntegration] bind #getGeofenceHardware() with the GeofenceProxy
+ FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
+ FusedProxy fusedProxy = FusedProxy.createAndBind(
+ mContext,
+ mLocationHandler,
+ flpHardwareProvider.getLocationHardware());
+
+ if(fusedProxy == null) {
+ Slog.e(TAG, "No FusedProvider found.");
+ }
}
/**
@@ -552,8 +565,14 @@ public class LocationManagerService extends ILocationManager.Stub {
allowHighPower = false;
}
}
+ boolean wasHighPowerMonitoring = mOpHighPowerMonitoring;
mOpHighPowerMonitoring = updateMonitoring(allowHighPower, mOpHighPowerMonitoring,
AppOpsManager.OP_MONITOR_HIGH_POWER_LOCATION);
+ if (mOpHighPowerMonitoring != wasHighPowerMonitoring) {
+ // send an intent to notify that a high power request has been added/removed.
+ Intent intent = new Intent(LocationManager.HIGH_POWER_REQUEST_CHANGE_ACTION);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
+ }
}
/**
diff --git a/services/java/com/android/server/accessibility/TouchExplorer.java b/services/java/com/android/server/accessibility/TouchExplorer.java
index 18b46fb..8fb3998 100644
--- a/services/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/java/com/android/server/accessibility/TouchExplorer.java
@@ -41,6 +41,7 @@ import com.android.internal.R;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* This class is a strategy for performing touch exploration. It
@@ -52,10 +53,8 @@ import java.util.Arrays;
* <li>2. One finger moving fast around performs gestures.</li>
* <li>3. Two close fingers moving in the same direction perform a drag.</li>
* <li>4. Multi-finger gestures are delivered to view hierarchy.</li>
- * <li>5. Pointers that have not moved more than a specified distance after they
- * went down are considered inactive.</li>
- * <li>6. Two fingers moving in different directions are considered a multi-finger gesture.</li>
- * <li>7. Double tapping clicks on the on the last touch explored location of it was in
+ * <li>5. Two fingers moving in different directions are considered a multi-finger gesture.</li>
+ * <li>7. Double tapping clicks on the on the last touch explored location if it was in
* a window that does not take focus, otherwise the click is within the accessibility
* focused rectangle.</li>
* <li>7. Tapping and holding for a while performs a long press in a similar fashion
@@ -102,9 +101,6 @@ class TouchExplorer implements EventStreamTransformation {
// The timeout after which we are no longer trying to detect a gesture.
private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
- // Temporary array for storing pointer IDs.
- private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
-
// Timeout before trying to decide what the user is trying to do.
private final int mDetermineUserIntentTimeout;
@@ -129,11 +125,11 @@ class TouchExplorer implements EventStreamTransformation {
// Handler for performing asynchronous operations.
private final Handler mHandler;
- // Command for delayed sending of a hover enter event.
- private final SendHoverDelayed mSendHoverEnterDelayed;
+ // Command for delayed sending of a hover enter and move event.
+ private final SendHoverEnterAndMoveDelayed mSendHoverEnterAndMoveDelayed;
// Command for delayed sending of a hover exit event.
- private final SendHoverDelayed mSendHoverExitDelayed;
+ private final SendHoverExitDelayed mSendHoverExitDelayed;
// Command for delayed sending of touch exploration end events.
private final SendAccessibilityEventDelayed mSendTouchExplorationEndDelayed;
@@ -220,7 +216,7 @@ class TouchExplorer implements EventStreamTransformation {
public TouchExplorer(Context context, AccessibilityManagerService service) {
mContext = context;
mAms = service;
- mReceivedPointerTracker = new ReceivedPointerTracker(context);
+ mReceivedPointerTracker = new ReceivedPointerTracker();
mInjectedPointerTracker = new InjectedPointerTracker();
mTapTimeout = ViewConfiguration.getTapTimeout();
mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout();
@@ -234,8 +230,8 @@ class TouchExplorer implements EventStreamTransformation {
mGestureLibrary.setOrientationStyle(8);
mGestureLibrary.setSequenceType(GestureStore.SEQUENCE_SENSITIVE);
mGestureLibrary.load();
- mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
- mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
+ mSendHoverEnterAndMoveDelayed = new SendHoverEnterAndMoveDelayed();
+ mSendHoverExitDelayed = new SendHoverExitDelayed();
mSendTouchExplorationEndDelayed = new SendAccessibilityEventDelayed(
AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
mDetermineUserIntentTimeout);
@@ -283,12 +279,12 @@ class TouchExplorer implements EventStreamTransformation {
} break;
}
// Remove all pending callbacks.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
- mExitGestureDetectionModeDelayed.remove();
- mSendTouchExplorationEndDelayed.remove();
- mSendTouchInteractionEndDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
+ mExitGestureDetectionModeDelayed.cancel();
+ mSendTouchExplorationEndDelayed.cancel();
+ mSendTouchInteractionEndDelayed.cancel();
// Reset the pointer trackers.
mReceivedPointerTracker.clear();
mInjectedPointerTracker.clear();
@@ -347,7 +343,7 @@ class TouchExplorer implements EventStreamTransformation {
// last hover exit event.
if (mSendTouchExplorationEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mSendTouchExplorationEndDelayed.remove();
+ mSendTouchExplorationEndDelayed.cancel();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
}
@@ -355,7 +351,7 @@ class TouchExplorer implements EventStreamTransformation {
// last hover exit and the touch exploration gesture end events.
if (mSendTouchInteractionEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
- mSendTouchInteractionEndDelayed.remove();
+ mSendTouchInteractionEndDelayed.cancel();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
}
@@ -390,95 +386,80 @@ class TouchExplorer implements EventStreamTransformation {
private void handleMotionEventStateTouchExploring(MotionEvent event, MotionEvent rawEvent,
int policyFlags) {
ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
- final int activePointerCount = receivedTracker.getActivePointerCount();
mVelocityTracker.addMovement(rawEvent);
mDoubleTapDetector.onMotionEvent(event, policyFlags);
switch (event.getActionMasked()) {
- case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_DOWN: {
mAms.onTouchInteractionStart();
+
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
// decreases the quality of gesture recognition.
handleMotionEventGestureDetecting(rawEvent, policyFlags);
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_DOWN: {
- switch (activePointerCount) {
- case 0: {
- throw new IllegalStateException("The must always be one active pointer in"
- + "touch exploring state!");
- }
- case 1: {
- // If we still have not notified the user for the last
- // touch, we figure out what to do. If were waiting
- // we resent the delayed callback and wait again.
- if (mSendHoverEnterDelayed.isPending()) {
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- }
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
- if (mSendTouchExplorationEndDelayed.isPending()) {
- mSendTouchExplorationEndDelayed.forceSendAndRemove();
- }
+ // If we still have not notified the user for the last
+ // touch, we figure out what to do. If were waiting
+ // we resent the delayed callback and wait again.
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
- if (mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.forceSendAndRemove();
- }
+ if (mSendTouchExplorationEndDelayed.isPending()) {
+ mSendTouchExplorationEndDelayed.forceSendAndRemove();
+ }
- // Every pointer that goes down is active until it moves or
- // another one goes down. Hence, having more than one pointer
- // down we have already send the interaction start event.
- if (event.getPointerCount() == 1) {
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
- }
+ if (mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.forceSendAndRemove();
+ }
- mPerformLongPressDelayed.remove();
-
- // If we have the first tap schedule a long press and break
- // since we do not want to schedule hover enter because
- // the delayed callback will kick in before the long click.
- // This would lead to a state transition resulting in long
- // pressing the item below the double taped area which is
- // not necessary where accessibility focus is.
- if (mDoubleTapDetector.firstTapDetected()) {
- // We got a tap now post a long press action.
- mPerformLongPressDelayed.post(event, policyFlags);
- break;
- }
- if (!mTouchExplorationInProgress) {
- // Deliver hover enter with a delay to have a chance
- // to detect what the user is trying to do.
- final int pointerId = receivedTracker.getPrimaryActivePointerId();
- final int pointerIdBits = (1 << pointerId);
- mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags);
- }
- } break;
- default: {
- /* do nothing - let the code for ACTION_MOVE decide what to do */
- } break;
+ // Cache the event until we discern exploration from gesturing.
+ mSendHoverEnterAndMoveDelayed.addEvent(event);
+
+ // If we have the first tap, schedule a long press and break
+ // since we do not want to schedule hover enter because
+ // the delayed callback will kick in before the long click.
+ // This would lead to a state transition resulting in long
+ // pressing the item below the double taped area which is
+ // not necessary where accessibility focus is.
+ if (mDoubleTapDetector.firstTapDetected()) {
+ // We got a tap now post a long press action.
+ mPerformLongPressDelayed.post(event, policyFlags);
+ break;
}
+ if (!mTouchExplorationInProgress) {
+ // Deliver hover enter with a delay to have a chance
+ // to detect what the user is trying to do.
+ final int pointerId = receivedTracker.getPrimaryPointerId();
+ final int pointerIdBits = (1 << pointerId);
+ mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, policyFlags);
+ }
+ } break;
+ case MotionEvent.ACTION_POINTER_DOWN: {
+ /* do nothing - let the code for ACTION_MOVE decide what to do */
} break;
case MotionEvent.ACTION_MOVE: {
- final int pointerId = receivedTracker.getPrimaryActivePointerId();
+ final int pointerId = receivedTracker.getPrimaryPointerId();
final int pointerIndex = event.findPointerIndex(pointerId);
final int pointerIdBits = (1 << pointerId);
- switch (activePointerCount) {
- case 0: {
- /* do nothing - no active pointers so we swallow the event */
- } break;
+ switch (event.getPointerCount()) {
case 1: {
// We have not started sending events since we try to
// figure out what the user is doing.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
// decreases the quality of gesture recognition.
handleMotionEventGestureDetecting(rawEvent, policyFlags);
+
+ // Cache the event until we discern exploration from gesturing.
+ mSendHoverEnterAndMoveDelayed.addEvent(event);
+
// It is *important* to use the distance traveled by the pointers
// on the screen which may or may not be magnified.
final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId)
@@ -500,9 +481,9 @@ class TouchExplorer implements EventStreamTransformation {
// clear the current state and try to detect.
mCurrentState = STATE_GESTURE_DETECTING;
mVelocityTracker.clear();
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
mExitGestureDetectionModeDelayed.post();
// Send accessibility event to announce the start
// of gesture recognition.
@@ -511,9 +492,9 @@ class TouchExplorer implements EventStreamTransformation {
} else {
// We have just decided that the user is touch,
// exploring so start sending events.
- mSendHoverEnterDelayed.forceSendAndRemove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE,
pointerIdBits, policyFlags);
}
@@ -532,11 +513,11 @@ class TouchExplorer implements EventStreamTransformation {
final double moveDelta = Math.hypot(deltaX, deltaY);
// The user has moved enough for us to decide.
if (moveDelta > mTouchSlop) {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
}
}
- // The user is wither double tapping or performing long
- // press so do not send move events yet.
+ // The user is either double tapping or performing a long
+ // press, so do not send move events yet.
if (mDoubleTapDetector.firstTapDetected()) {
break;
}
@@ -548,14 +529,14 @@ class TouchExplorer implements EventStreamTransformation {
case 2: {
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// We have not started sending events so cancel
// scheduled sending events.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
// If the user is touch exploring the second pointer may be
// performing a double tap to activate an item without need
// for the user to lift his exploring finger.
@@ -590,21 +571,21 @@ class TouchExplorer implements EventStreamTransformation {
} else {
// Two pointers moving arbitrary are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
mVelocityTracker.clear();
} break;
default: {
// More than one pointer so the user is not touch exploring
// and now we have to decide whether to delegate or drag.
- if (mSendHoverEnterDelayed.isPending()) {
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
// We have not started sending events so cancel
// scheduled sending events.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
} else {
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
// We are sending events so send exit and gesture
// end since we transition to another state.
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
@@ -612,43 +593,34 @@ class TouchExplorer implements EventStreamTransformation {
// More than two pointers are delegated to the view hierarchy.
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
mVelocityTracker.clear();
}
}
} break;
- case MotionEvent.ACTION_UP:
+ case MotionEvent.ACTION_UP: {
mAms.onTouchInteractionEnd();
// We know that we do not need the pre-fed gesture points are not
// needed anymore since the last pointer just went up.
mStrokeBuffer.clear();
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_UP: {
- final int pointerId = receivedTracker.getLastReceivedUpPointerId();
+ final int pointerId = event.getPointerId(event.getActionIndex());
final int pointerIdBits = (1 << pointerId);
- switch (activePointerCount) {
- case 0: {
- // If the pointer that went up was not active we have nothing to do.
- if (!receivedTracker.wasLastReceivedUpPointerActive()) {
- break;
- }
- mPerformLongPressDelayed.remove();
+ mPerformLongPressDelayed.cancel();
+ mVelocityTracker.clear();
- // If we have not delivered the enter schedule exit.
- if (mSendHoverEnterDelayed.isPending()) {
- mSendHoverExitDelayed.post(event, false, pointerIdBits, policyFlags);
- } else {
- // The user is touch exploring so we send events for end.
- sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
- }
+ if (mSendHoverEnterAndMoveDelayed.isPending()) {
+ // If we have not delivered the enter schedule an exit.
+ mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags);
+ } else {
+ // The user is touch exploring so we send events for end.
+ sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
+ }
- if (!mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.post();
- }
- } break;
+ if (!mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.post();
}
- mVelocityTracker.clear();
+
} break;
case MotionEvent.ACTION_CANCEL: {
clear(event, policyFlags);
@@ -676,29 +648,19 @@ class TouchExplorer implements EventStreamTransformation {
if (mDraggingPointerId != INVALID_POINTER_ID) {
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags);
}
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ sendDownForAllNotInjectedPointers(event, policyFlags);
} break;
case MotionEvent.ACTION_MOVE: {
- final int activePointerCount = mReceivedPointerTracker.getActivePointerCount();
- switch (activePointerCount) {
+ switch (event.getPointerCount()) {
case 1: {
// do nothing
} break;
case 2: {
if (isDraggingGesture(event)) {
- // If the dragging pointer are closer that a given distance we
- // use the location of the primary one. Otherwise, we take the
- // middle between the pointers.
- int[] pointerIds = mTempPointerIds;
- mReceivedPointerTracker.populateActivePointerIds(pointerIds);
-
- final int firstPtrIndex = event.findPointerIndex(pointerIds[0]);
- final int secondPtrIndex = event.findPointerIndex(pointerIds[1]);
-
- final float firstPtrX = event.getX(firstPtrIndex);
- final float firstPtrY = event.getY(firstPtrIndex);
- final float secondPtrX = event.getX(secondPtrIndex);
- final float secondPtrY = event.getY(secondPtrIndex);
+ final float firstPtrX = event.getX(0);
+ final float firstPtrY = event.getY(0);
+ final float secondPtrX = event.getX(1);
+ final float secondPtrY = event.getY(1);
final float deltaX = firstPtrX - secondPtrX;
final float deltaY = firstPtrY - secondPtrY;
@@ -718,8 +680,8 @@ class TouchExplorer implements EventStreamTransformation {
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
policyFlags);
- // Deliver all active pointers to the view hierarchy.
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ // Deliver all pointers to the view hierarchy.
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
} break;
default: {
@@ -727,8 +689,8 @@ class TouchExplorer implements EventStreamTransformation {
// Send an event to the end of the drag gesture.
sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits,
policyFlags);
- // Deliver all active pointers to the view hierarchy.
- sendDownForAllActiveNotInjectedPointers(event, policyFlags);
+ // Deliver all pointers to the view hierarchy.
+ sendDownForAllNotInjectedPointers(event, policyFlags);
}
}
} break;
@@ -771,37 +733,21 @@ class TouchExplorer implements EventStreamTransformation {
throw new IllegalStateException("Delegating state can only be reached if "
+ "there is at least one pointer down!");
}
- case MotionEvent.ACTION_MOVE: {
- // Check whether some other pointer became active because they have moved
- // a given distance and if such exist send them to the view hierarchy
- final int notInjectedCount = getNotInjectedActivePointerCount(
- mReceivedPointerTracker, mInjectedPointerTracker);
- if (notInjectedCount > 0) {
- MotionEvent prototype = MotionEvent.obtain(event);
- sendDownForAllActiveNotInjectedPointers(prototype, policyFlags);
- }
- } break;
- case MotionEvent.ACTION_UP:
- // Announce the end of a new touch interaction.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
- //$FALL-THROUGH$
- case MotionEvent.ACTION_POINTER_UP: {
+ case MotionEvent.ACTION_UP: {
+ // Announce the end of a the touch interaction.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
mAms.onTouchInteractionEnd();
mLongPressingPointerId = -1;
mLongPressingPointerDeltaX = 0;
mLongPressingPointerDeltaY = 0;
- // No active pointers => go to initial state.
- if (mReceivedPointerTracker.getActivePointerCount() == 0) {
- mCurrentState = STATE_TOUCH_EXPLORING;
- }
+ mCurrentState = STATE_TOUCH_EXPLORING;
} break;
case MotionEvent.ACTION_CANCEL: {
clear(event, policyFlags);
} break;
}
- // Deliver the event striping out inactive pointers.
- sendMotionEventStripInactivePointers(event, policyFlags);
+ // Deliver the event.
+ sendMotionEvent(event, event.getAction(), ALL_POINTER_ID_BITS, policyFlags);
}
private void handleMotionEventGestureDetecting(MotionEvent event, int policyFlags) {
@@ -826,12 +772,10 @@ class TouchExplorer implements EventStreamTransformation {
} break;
case MotionEvent.ACTION_UP: {
mAms.onTouchInteractionEnd();
- // Announce the end of gesture recognition.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
- // Announce the end of a new touch interaction.
- sendAccessibilityEvent(
- AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
+ // Announce the end of the gesture recognition.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_GESTURE_DETECTION_END);
+ // Announce the end of a the touch interaction.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
float x = event.getX();
float y = event.getY();
@@ -858,7 +802,7 @@ class TouchExplorer implements EventStreamTransformation {
}
mStrokeBuffer.clear();
- mExitGestureDetectionModeDelayed.remove();
+ mExitGestureDetectionModeDelayed.cancel();
mCurrentState = STATE_TOUCH_EXPLORING;
} break;
case MotionEvent.ACTION_CANCEL: {
@@ -889,40 +833,26 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Sends down events to the view hierarchy for all active pointers which are
+ * Sends down events to the view hierarchy for all pointers which are
* not already being delivered i.e. pointers that are not yet injected.
*
* @param prototype The prototype from which to create the injected events.
* @param policyFlags The policy flags associated with the event.
*/
- private void sendDownForAllActiveNotInjectedPointers(MotionEvent prototype, int policyFlags) {
- ReceivedPointerTracker receivedPointers = mReceivedPointerTracker;
+ private void sendDownForAllNotInjectedPointers(MotionEvent prototype, int policyFlags) {
InjectedPointerTracker injectedPointers = mInjectedPointerTracker;
+
+ // Inject the injected pointers.
int pointerIdBits = 0;
final int pointerCount = prototype.getPointerCount();
-
- // Find which pointers are already injected.
- for (int i = 0; i < pointerCount; i++) {
- final int pointerId = prototype.getPointerId(i);
- if (injectedPointers.isInjectedPointerDown(pointerId)) {
- pointerIdBits |= (1 << pointerId);
- }
- }
-
- // Inject the active and not injected pointers.
for (int i = 0; i < pointerCount; i++) {
final int pointerId = prototype.getPointerId(i);
- // Skip inactive pointers.
- if (!receivedPointers.isActivePointer(pointerId)) {
- continue;
- }
// Do not send event for already delivered pointers.
- if (injectedPointers.isInjectedPointerDown(pointerId)) {
- continue;
+ if (!injectedPointers.isInjectedPointerDown(pointerId)) {
+ pointerIdBits |= (1 << pointerId);
+ final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
+ sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
}
- pointerIdBits |= (1 << pointerId);
- final int action = computeInjectionAction(MotionEvent.ACTION_DOWN, i);
- sendMotionEvent(prototype, action, pointerIdBits, policyFlags);
}
}
@@ -959,7 +889,7 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Sends up events to the view hierarchy for all active pointers which are
+ * Sends up events to the view hierarchy for all pointers which are
* already being delivered i.e. pointers that are injected.
*
* @param prototype The prototype from which to create the injected events.
@@ -982,58 +912,13 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Sends a motion event by first stripping the inactive pointers.
- *
- * @param prototype The prototype from which to create the injected event.
- * @param policyFlags The policy flags associated with the event.
- */
- private void sendMotionEventStripInactivePointers(MotionEvent prototype, int policyFlags) {
- ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
-
- // All pointers active therefore we just inject the event as is.
- if (prototype.getPointerCount() == receivedTracker.getActivePointerCount()) {
- sendMotionEvent(prototype, prototype.getAction(), ALL_POINTER_ID_BITS, policyFlags);
- return;
- }
-
- // No active pointers and the one that just went up was not
- // active, therefore we have nothing to do.
- if (receivedTracker.getActivePointerCount() == 0
- && !receivedTracker.wasLastReceivedUpPointerActive()) {
- return;
- }
-
- // If the action pointer going up/down is not active we have nothing to do.
- // However, for moves we keep going to report moves of active pointers.
- final int actionMasked = prototype.getActionMasked();
- final int actionPointerId = prototype.getPointerId(prototype.getActionIndex());
- if (actionMasked != MotionEvent.ACTION_MOVE) {
- if (!receivedTracker.isActiveOrWasLastActiveUpPointer(actionPointerId)) {
- return;
- }
- }
-
- // If the pointer is active or the pointer that just went up
- // was active we keep the pointer data in the event.
- int pointerIdBits = 0;
- final int pointerCount = prototype.getPointerCount();
- for (int pointerIndex = 0; pointerIndex < pointerCount; pointerIndex++) {
- final int pointerId = prototype.getPointerId(pointerIndex);
- if (receivedTracker.isActiveOrWasLastActiveUpPointer(pointerId)) {
- pointerIdBits |= (1 << pointerId);
- }
- }
- sendMotionEvent(prototype, prototype.getAction(), pointerIdBits, policyFlags);
- }
-
- /**
* Sends an up and down events.
*
* @param prototype The prototype from which to create the injected events.
* @param policyFlags The policy flags associated with the event.
*/
private void sendActionDownAndUp(MotionEvent prototype, int policyFlags) {
- // Tap with the pointer that last explored - we may have inactive pointers.
+ // Tap with the pointer that last explored.
final int pointerId = prototype.getPointerId(prototype.getActionIndex());
final int pointerIdBits = (1 << pointerId);
sendMotionEvent(prototype, MotionEvent.ACTION_DOWN, pointerIdBits, policyFlags);
@@ -1215,9 +1100,9 @@ class TouchExplorer implements EventStreamTransformation {
}
// Remove pending event deliveries.
- mSendHoverEnterDelayed.remove();
- mSendHoverExitDelayed.remove();
- mPerformLongPressDelayed.remove();
+ mSendHoverEnterAndMoveDelayed.cancel();
+ mSendHoverExitDelayed.cancel();
+ mPerformLongPressDelayed.cancel();
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
@@ -1307,21 +1192,16 @@ class TouchExplorer implements EventStreamTransformation {
*/
private boolean isDraggingGesture(MotionEvent event) {
ReceivedPointerTracker receivedTracker = mReceivedPointerTracker;
- int[] pointerIds = mTempPointerIds;
- receivedTracker.populateActivePointerIds(pointerIds);
-
- final int firstPtrIndex = event.findPointerIndex(pointerIds[0]);
- final int secondPtrIndex = event.findPointerIndex(pointerIds[1]);
- final float firstPtrX = event.getX(firstPtrIndex);
- final float firstPtrY = event.getY(firstPtrIndex);
- final float secondPtrX = event.getX(secondPtrIndex);
- final float secondPtrY = event.getY(secondPtrIndex);
+ final float firstPtrX = event.getX(0);
+ final float firstPtrY = event.getY(0);
+ final float secondPtrX = event.getX(1);
+ final float secondPtrY = event.getY(1);
- final float firstPtrDownX = receivedTracker.getReceivedPointerDownX(firstPtrIndex);
- final float firstPtrDownY = receivedTracker.getReceivedPointerDownY(firstPtrIndex);
- final float secondPtrDownX = receivedTracker.getReceivedPointerDownX(secondPtrIndex);
- final float secondPtrDownY = receivedTracker.getReceivedPointerDownY(secondPtrIndex);
+ final float firstPtrDownX = receivedTracker.getReceivedPointerDownX(0);
+ final float firstPtrDownY = receivedTracker.getReceivedPointerDownY(0);
+ final float secondPtrDownX = receivedTracker.getReceivedPointerDownX(1);
+ final float secondPtrDownY = receivedTracker.getReceivedPointerDownY(1);
return GestureUtils.isDraggingGesture(firstPtrDownX, firstPtrDownY, secondPtrDownX,
secondPtrDownY, firstPtrX, firstPtrY, secondPtrX, secondPtrY,
@@ -1350,16 +1230,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return The number of non injected active pointers.
- */
- private int getNotInjectedActivePointerCount(ReceivedPointerTracker receivedTracker,
- InjectedPointerTracker injectedTracker) {
- final int pointerState = receivedTracker.getActivePointers()
- & ~injectedTracker.getInjectedPointersDown();
- return Integer.bitCount(pointerState);
- }
-
- /**
* Class for delayed exiting from gesture detecting mode.
*/
private final class ExitGestureDetectionModeDelayed implements Runnable {
@@ -1368,7 +1238,7 @@ class TouchExplorer implements EventStreamTransformation {
mHandler.postDelayed(this, EXIT_GESTURE_DETECTION_TIMEOUT);
}
- public void remove() {
+ public void cancel() {
mHandler.removeCallbacks(this);
}
@@ -1396,21 +1266,21 @@ class TouchExplorer implements EventStreamTransformation {
mHandler.postDelayed(this, ViewConfiguration.getLongPressTimeout());
}
- public void remove() {
- if (isPending()) {
+ public void cancel() {
+ if (mEvent != null) {
mHandler.removeCallbacks(this);
clear();
}
}
- public boolean isPending() {
- return (mEvent != null);
+ private boolean isPending() {
+ return mHandler.hasCallbacks(this);
}
@Override
public void run() {
- // Active pointers should not be zero when running this command.
- if (mReceivedPointerTracker.getActivePointerCount() == 0) {
+ // Pointers should not be zero when running this command.
+ if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) {
return;
}
@@ -1461,14 +1331,11 @@ class TouchExplorer implements EventStreamTransformation {
sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags);
mCurrentState = STATE_DELEGATING;
- sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
+ sendDownForAllNotInjectedPointers(mEvent, mPolicyFlags);
clear();
}
private void clear() {
- if (!isPending()) {
- return;
- }
mEvent.recycle();
mEvent = null;
mPolicyFlags = 0;
@@ -1476,59 +1343,114 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Class for delayed sending of hover events.
+ * Class for delayed sending of hover enter and move events.
*/
- class SendHoverDelayed implements Runnable {
- private final String LOG_TAG_SEND_HOVER_DELAYED = SendHoverDelayed.class.getName();
+ class SendHoverEnterAndMoveDelayed implements Runnable {
+ private final String LOG_TAG_SEND_HOVER_DELAYED = "SendHoverEnterAndMoveDelayed";
- private final int mHoverAction;
- private final boolean mGestureStarted;
+ private final List<MotionEvent> mEvents = new ArrayList<MotionEvent>();
- private MotionEvent mPrototype;
private int mPointerIdBits;
private int mPolicyFlags;
- public SendHoverDelayed(int hoverAction, boolean gestureStarted) {
- mHoverAction = hoverAction;
- mGestureStarted = gestureStarted;
- }
-
- public void post(MotionEvent prototype, boolean touchExplorationInProgress,
+ public void post(MotionEvent event, boolean touchExplorationInProgress,
int pointerIdBits, int policyFlags) {
- remove();
- mPrototype = MotionEvent.obtain(prototype);
+ cancel();
+ addEvent(event);
mPointerIdBits = pointerIdBits;
mPolicyFlags = policyFlags;
mHandler.postDelayed(this, mDetermineUserIntentTimeout);
}
- public float getX() {
+ public void addEvent(MotionEvent event) {
+ mEvents.add(MotionEvent.obtain(event));
+ }
+
+ public void cancel() {
if (isPending()) {
- return mPrototype.getX();
+ mHandler.removeCallbacks(this);
+ clear();
+ }
+ }
+
+ private boolean isPending() {
+ return mHandler.hasCallbacks(this);
+ }
+
+ private void clear() {
+ mPointerIdBits = -1;
+ mPolicyFlags = 0;
+ final int eventCount = mEvents.size();
+ for (int i = eventCount - 1; i >= 0; i--) {
+ mEvents.remove(i).recycle();
}
- return 0;
}
- public float getY() {
+ public void forceSendAndRemove() {
if (isPending()) {
- return mPrototype.getY();
+ run();
+ cancel();
}
- return 0;
}
- public void remove() {
- mHandler.removeCallbacks(this);
+ public void run() {
+ // Send an accessibility event to announce the touch exploration start.
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
+
+ if (!mEvents.isEmpty()) {
+ // Deliver a down event.
+ sendMotionEvent(mEvents.get(0), MotionEvent.ACTION_HOVER_ENTER,
+ mPointerIdBits, mPolicyFlags);
+ if (DEBUG) {
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED,
+ "Injecting motion event: ACTION_HOVER_ENTER");
+ }
+
+ // Deliver move events.
+ final int eventCount = mEvents.size();
+ for (int i = 1; i < eventCount; i++) {
+ sendMotionEvent(mEvents.get(i), MotionEvent.ACTION_HOVER_MOVE,
+ mPointerIdBits, mPolicyFlags);
+ if (DEBUG) {
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED,
+ "Injecting motion event: ACTION_HOVER_MOVE");
+ }
+ }
+ }
clear();
}
+ }
+
+ /**
+ * Class for delayed sending of hover exit events.
+ */
+ class SendHoverExitDelayed implements Runnable {
+ private final String LOG_TAG_SEND_HOVER_DELAYED = "SendHoverExitDelayed";
+
+ private MotionEvent mPrototype;
+ private int mPointerIdBits;
+ private int mPolicyFlags;
+
+ public void post(MotionEvent prototype, int pointerIdBits, int policyFlags) {
+ cancel();
+ mPrototype = MotionEvent.obtain(prototype);
+ mPointerIdBits = pointerIdBits;
+ mPolicyFlags = policyFlags;
+ mHandler.postDelayed(this, mDetermineUserIntentTimeout);
+ }
+
+ public void cancel() {
+ if (isPending()) {
+ mHandler.removeCallbacks(this);
+ clear();
+ }
+ }
private boolean isPending() {
- return (mPrototype != null);
+ return mHandler.hasCallbacks(this);
}
private void clear() {
- if (!isPending()) {
- return;
- }
mPrototype.recycle();
mPrototype = null;
mPointerIdBits = -1;
@@ -1538,29 +1460,25 @@ class TouchExplorer implements EventStreamTransformation {
public void forceSendAndRemove() {
if (isPending()) {
run();
- remove();
+ cancel();
}
}
public void run() {
if (DEBUG) {
- Slog.d(LOG_TAG_SEND_HOVER_DELAYED, "Injecting motion event: "
- + MotionEvent.actionToString(mHoverAction));
- Slog.d(LOG_TAG_SEND_HOVER_DELAYED, mGestureStarted ?
- "touchExplorationGestureStarted" : "touchExplorationGestureEnded");
+ Slog.d(LOG_TAG_SEND_HOVER_DELAYED, "Injecting motion event:"
+ + " ACTION_HOVER_EXIT");
}
- if (mGestureStarted) {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
- } else {
- if (!mSendTouchExplorationEndDelayed.isPending()) {
- mSendTouchExplorationEndDelayed.post();
- }
- if (mSendTouchInteractionEndDelayed.isPending()) {
- mSendTouchInteractionEndDelayed.remove();
- mSendTouchInteractionEndDelayed.post();
- }
+ sendMotionEvent(mPrototype, MotionEvent.ACTION_HOVER_EXIT,
+ mPointerIdBits, mPolicyFlags);
+ if (!mSendTouchExplorationEndDelayed.isPending()) {
+ mSendTouchExplorationEndDelayed.cancel();
+ mSendTouchExplorationEndDelayed.post();
+ }
+ if (mSendTouchInteractionEndDelayed.isPending()) {
+ mSendTouchInteractionEndDelayed.cancel();
+ mSendTouchInteractionEndDelayed.post();
}
- sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
clear();
}
}
@@ -1574,7 +1492,7 @@ class TouchExplorer implements EventStreamTransformation {
mDelay = delay;
}
- public void remove() {
+ public void cancel() {
mHandler.removeCallbacks(this);
}
@@ -1589,7 +1507,7 @@ class TouchExplorer implements EventStreamTransformation {
public void forceSendAndRemove() {
if (isPending()) {
run();
- remove();
+ cancel();
}
}
@@ -1736,15 +1654,6 @@ class TouchExplorer implements EventStreamTransformation {
class ReceivedPointerTracker {
private static final String LOG_TAG_RECEIVED_POINTER_TRACKER = "ReceivedPointerTracker";
- // The coefficient by which to multiply
- // ViewConfiguration.#getScaledTouchSlop()
- // to compute #mThresholdActivePointer.
- private static final int COEFFICIENT_ACTIVE_POINTER = 2;
-
- // Pointers that moved less than mThresholdActivePointer
- // are considered active i.e. are ignored.
- private final double mThresholdActivePointer;
-
// Keep track of where and when a pointer went down.
private final float[] mReceivedPointerDownX = new float[MAX_POINTER_COUNT];
private final float[] mReceivedPointerDownY = new float[MAX_POINTER_COUNT];
@@ -1756,36 +1665,19 @@ class TouchExplorer implements EventStreamTransformation {
// The edge flags of the last received down event.
private int mLastReceivedDownEdgeFlags;
- // Which down pointers are active.
- private int mActivePointers;
-
- // Primary active pointer which is either the first that went down
- // or if it goes up the next active that most recently went down.
- private int mPrimaryActivePointerId;
-
- // Flag indicating that there is at least one active pointer moving.
- private boolean mHasMovingActivePointer;
+ // Primary pointer which is either the first that went down
+ // or if it goes up the next one that most recently went down.
+ private int mPrimaryPointerId;
// Keep track of the last up pointer data.
private long mLastReceivedUpPointerDownTime;
private int mLastReceivedUpPointerId;
- private boolean mLastReceivedUpPointerActive;
private float mLastReceivedUpPointerDownX;
private float mLastReceivedUpPointerDownY;
private MotionEvent mLastReceivedEvent;
/**
- * Creates a new instance.
- *
- * @param context Context for looking up resources.
- */
- public ReceivedPointerTracker(Context context) {
- mThresholdActivePointer =
- ViewConfiguration.get(context).getScaledTouchSlop() * COEFFICIENT_ACTIVE_POINTER;
- }
-
- /**
* Clears the internals state.
*/
public void clear() {
@@ -1793,12 +1685,9 @@ class TouchExplorer implements EventStreamTransformation {
Arrays.fill(mReceivedPointerDownY, 0);
Arrays.fill(mReceivedPointerDownTime, 0);
mReceivedPointersDown = 0;
- mActivePointers = 0;
- mPrimaryActivePointerId = 0;
- mHasMovingActivePointer = false;
+ mPrimaryPointerId = 0;
mLastReceivedUpPointerDownTime = 0;
mLastReceivedUpPointerId = 0;
- mLastReceivedUpPointerActive = false;
mLastReceivedUpPointerDownX = 0;
mLastReceivedUpPointerDownY = 0;
}
@@ -1822,9 +1711,6 @@ class TouchExplorer implements EventStreamTransformation {
case MotionEvent.ACTION_POINTER_DOWN: {
handleReceivedPointerDown(event.getActionIndex(), event);
} break;
- case MotionEvent.ACTION_MOVE: {
- handleReceivedPointerMove(event);
- } break;
case MotionEvent.ACTION_UP: {
handleReceivedPointerUp(event.getActionIndex(), event);
} break;
@@ -1852,20 +1738,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return The bits of the pointers that are active.
- */
- public int getActivePointers() {
- return mActivePointers;
- }
-
- /**
- * @return The number of down input pointers that are active.
- */
- public int getActivePointerCount() {
- return Integer.bitCount(mActivePointers);
- }
-
- /**
* Whether an received pointer is down.
*
* @param pointerId The unique pointer id.
@@ -1877,17 +1749,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * Whether an input pointer is active.
- *
- * @param pointerId The unique pointer id.
- * @return True if the pointer is active.
- */
- public boolean isActivePointer(int pointerId) {
- final int pointerFlag = (1 << pointerId);
- return (mActivePointers & pointerFlag) != 0;
- }
-
- /**
* @param pointerId The unique pointer id.
* @return The X coordinate where the pointer went down.
*/
@@ -1914,11 +1775,11 @@ class TouchExplorer implements EventStreamTransformation {
/**
* @return The id of the primary pointer.
*/
- public int getPrimaryActivePointerId() {
- if (mPrimaryActivePointerId == INVALID_POINTER_ID) {
- mPrimaryActivePointerId = findPrimaryActivePointer();
+ public int getPrimaryPointerId() {
+ if (mPrimaryPointerId == INVALID_POINTER_ID) {
+ mPrimaryPointerId = findPrimaryPointer();
}
- return mPrimaryActivePointerId;
+ return mPrimaryPointerId;
}
/**
@@ -1929,14 +1790,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return The id of the last received pointer that went up.
- */
- public int getLastReceivedUpPointerId() {
- return mLastReceivedUpPointerId;
- }
-
-
- /**
* @return The down X of the last received pointer that went up.
*/
public float getLastReceivedUpPointerDownX() {
@@ -1958,39 +1811,6 @@ class TouchExplorer implements EventStreamTransformation {
}
/**
- * @return Whether the last received pointer that went up was active.
- */
- public boolean wasLastReceivedUpPointerActive() {
- return mLastReceivedUpPointerActive;
- }
- /**
- * Populates the active pointer IDs to the given array.
- * <p>
- * Note: The client is responsible for providing large enough array.
- *
- * @param outPointerIds The array to which to write the active pointers.
- */
- public void populateActivePointerIds(int[] outPointerIds) {
- int index = 0;
- for (int idBits = mActivePointers; idBits != 0; ) {
- final int id = Integer.numberOfTrailingZeros(idBits);
- idBits &= ~(1 << id);
- outPointerIds[index] = id;
- index++;
- }
- }
-
- /**
- * @param pointerId The unique pointer id.
- * @return Whether the pointer is active or was the last active than went up.
- */
- public boolean isActiveOrWasLastActiveUpPointer(int pointerId) {
- return (isActivePointer(pointerId)
- || (mLastReceivedUpPointerId == pointerId
- && mLastReceivedUpPointerActive));
- }
-
- /**
* Handles a received pointer down event.
*
* @param pointerIndex The index of the pointer that has changed.
@@ -2002,7 +1822,6 @@ class TouchExplorer implements EventStreamTransformation {
mLastReceivedUpPointerId = 0;
mLastReceivedUpPointerDownTime = 0;
- mLastReceivedUpPointerActive = false;
mLastReceivedUpPointerDownX = 0;
mLastReceivedUpPointerDownX = 0;
@@ -2013,25 +1832,7 @@ class TouchExplorer implements EventStreamTransformation {
mReceivedPointerDownY[pointerId] = event.getY(pointerIndex);
mReceivedPointerDownTime[pointerId] = event.getEventTime();
- if (!mHasMovingActivePointer) {
- // If still no moving active pointers every
- // down pointer is the only active one.
- mActivePointers = pointerFlag;
- mPrimaryActivePointerId = pointerId;
- } else {
- // If at least one moving active pointer every
- // subsequent down pointer is active.
- mActivePointers |= pointerFlag;
- }
- }
-
- /**
- * Handles a received pointer move event.
- *
- * @param event The event to be handled.
- */
- private void handleReceivedPointerMove(MotionEvent event) {
- detectActivePointers(event);
+ mPrimaryPointerId = pointerId;
}
/**
@@ -2046,80 +1847,34 @@ class TouchExplorer implements EventStreamTransformation {
mLastReceivedUpPointerId = pointerId;
mLastReceivedUpPointerDownTime = getReceivedPointerDownTime(pointerId);
- mLastReceivedUpPointerActive = isActivePointer(pointerId);
mLastReceivedUpPointerDownX = mReceivedPointerDownX[pointerId];
mLastReceivedUpPointerDownY = mReceivedPointerDownY[pointerId];
mReceivedPointersDown &= ~pointerFlag;
- mActivePointers &= ~pointerFlag;
mReceivedPointerDownX[pointerId] = 0;
mReceivedPointerDownY[pointerId] = 0;
mReceivedPointerDownTime[pointerId] = 0;
- if (mActivePointers == 0) {
- mHasMovingActivePointer = false;
- }
- if (mPrimaryActivePointerId == pointerId) {
- mPrimaryActivePointerId = INVALID_POINTER_ID;
- }
- }
-
- /**
- * Detects the active pointers in an event.
- *
- * @param event The event to examine.
- */
- private void detectActivePointers(MotionEvent event) {
- for (int i = 0, count = event.getPointerCount(); i < count; i++) {
- final int pointerId = event.getPointerId(i);
- if (mHasMovingActivePointer) {
- // If already active => nothing to do.
- if (isActivePointer(pointerId)) {
- continue;
- }
- }
- // Active pointers are ones that moved more than a given threshold.
- final float pointerDeltaMove = computePointerDeltaMove(i, event);
- if (pointerDeltaMove > mThresholdActivePointer) {
- final int pointerFlag = (1 << pointerId);
- mActivePointers |= pointerFlag;
- mHasMovingActivePointer = true;
- }
+ if (mPrimaryPointerId == pointerId) {
+ mPrimaryPointerId = INVALID_POINTER_ID;
}
}
/**
- * @return The primary active pointer.
+ * @return The primary pointer.
*/
- private int findPrimaryActivePointer() {
- int primaryActivePointerId = INVALID_POINTER_ID;
+ private int findPrimaryPointer() {
+ int primaryPointerId = INVALID_POINTER_ID;
long minDownTime = Long.MAX_VALUE;
- // Find the active pointer that went down first.
+ // Find the pointer that went down first.
for (int i = 0, count = mReceivedPointerDownTime.length; i < count; i++) {
- if (isActivePointer(i)) {
- final long downPointerTime = mReceivedPointerDownTime[i];
- if (downPointerTime < minDownTime) {
- minDownTime = downPointerTime;
- primaryActivePointerId = i;
- }
+ final long downPointerTime = mReceivedPointerDownTime[i];
+ if (downPointerTime < minDownTime) {
+ minDownTime = downPointerTime;
+ primaryPointerId = i;
}
}
- return primaryActivePointerId;
- }
-
- /**
- * Computes the move for a given action pointer index since the
- * corresponding pointer went down.
- *
- * @param pointerIndex The action pointer index.
- * @param event The event to examine.
- * @return The distance the pointer has moved.
- */
- private float computePointerDeltaMove(int pointerIndex, MotionEvent event) {
- final int pointerId = event.getPointerId(pointerIndex);
- final float deltaX = event.getX(pointerIndex) - mReceivedPointerDownX[pointerId];
- final float deltaY = event.getY(pointerIndex) - mReceivedPointerDownY[pointerId];
- return (float) Math.hypot(deltaX, deltaY);
+ return primaryPointerId;
}
@Override
@@ -2136,18 +1891,8 @@ class TouchExplorer implements EventStreamTransformation {
}
}
builder.append("]");
- builder.append("\nActive pointers #");
- builder.append(getActivePointerCount());
- builder.append(" [ ");
- for (int i = 0; i < MAX_POINTER_COUNT; i++) {
- if (isActivePointer(i)) {
- builder.append(i);
- builder.append(" ");
- }
- }
- builder.append("]");
- builder.append("\nPrimary active pointer id [ ");
- builder.append(getPrimaryActivePointerId());
+ builder.append("\nPrimary pointer id [ ");
+ builder.append(getPrimaryPointerId());
builder.append(" ]");
builder.append("\n=========================");
return builder.toString();
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 3d8843e..9dba2ed 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -42,7 +42,7 @@ import com.android.internal.util.MemInfoReader;
import com.android.server.AppOpsService;
import com.android.server.AttributeCache;
import com.android.server.IntentResolver;
-import com.android.server.ProcessMap;
+import com.android.internal.app.ProcessMap;
import com.android.server.SystemServer;
import com.android.server.Watchdog;
import com.android.server.am.ActivityStack.ActivityState;
@@ -1554,11 +1554,11 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
ActivityManagerService m = mSelf;
- ServiceManager.addService("activity", m, true);
+ ServiceManager.addService(Context.ACTIVITY_SERVICE, m, true);
+ ServiceManager.addService(ProcessStats.SERVICE_NAME, m.mProcessStats);
ServiceManager.addService("meminfo", new MemBinder(m));
ServiceManager.addService("gfxinfo", new GraphicsBinder(m));
ServiceManager.addService("dbinfo", new DbBinder(m));
- ServiceManager.addService("procstats", new ProcBinder(m));
if (MONITOR_CPU_USAGE) {
ServiceManager.addService("cpuinfo", new CpuBinder(m));
}
@@ -1775,26 +1775,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- static class ProcBinder extends Binder {
- ActivityManagerService mActivityManagerService;
- ProcBinder(ActivityManagerService activityManagerService) {
- mActivityManagerService = activityManagerService;
- }
-
- @Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mActivityManagerService.checkCallingPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump procstats from from pid="
- + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
- + " without permission " + android.Manifest.permission.DUMP);
- return;
- }
-
- mActivityManagerService.mProcessStats.dump(fd, pw, args);
- }
- }
-
private ActivityManagerService() {
Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
@@ -8453,9 +8433,17 @@ public final class ActivityManagerService extends ActivityManagerNative
resolver, Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0;
boolean alwaysFinishActivities = Settings.Global.getInt(
resolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0;
+ boolean forceRtl = Settings.Global.getInt(
+ resolver, Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0;
+ // Transfer any global setting for forcing RTL layout, into a System Property
+ SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0");
Configuration configuration = new Configuration();
Settings.System.getConfiguration(resolver, configuration);
+ if (forceRtl) {
+ // This will take care of setting the correct layout direction flags
+ configuration.setLayoutDirection(configuration.locale);
+ }
synchronized (this) {
mDebugApp = mOrigDebugApp = debugApp;
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 8b4a5a0..6611a24 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -18,6 +18,8 @@ package com.android.server.am;
import android.app.AppGlobals;
import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.os.Binder;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -59,7 +61,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
static long WRITE_PERIOD = 30*60*1000; // Write file every 30 minutes or so.
static long COMMIT_PERIOD = 24*60*60*1000; // Commit current stats every day.
- final Object mLock;
+ final ActivityManagerService mAm;
final File mBaseDir;
ProcessStats mProcessStats;
AtomicFile mFile;
@@ -75,15 +77,15 @@ public final class ProcessStatsService extends IProcessStats.Stub {
boolean mPendingWriteCommitted;
long mLastWriteTime;
- public ProcessStatsService(Object lock, File file) {
- mLock = lock;
+ public ProcessStatsService(ActivityManagerService am, File file) {
+ mAm = am;
mBaseDir = file;
mBaseDir.mkdirs();
mProcessStats = new ProcessStats(true);
updateFile();
SystemProperties.addChangeCallback(new Runnable() {
@Override public void run() {
- synchronized (mLock) {
+ synchronized (mAm) {
if (mProcessStats.evaluateSystemProperties(false)) {
mProcessStats.mFlags |= ProcessStats.FLAG_SYSPROPS;
writeStateLocked(true, true);
@@ -101,17 +103,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
public ProcessStats.ServiceState getServiceStateLocked(String packageName, int uid,
String processName, String className) {
- final ProcessStats.PackageState as = mProcessStats.getPackageStateLocked(packageName, uid);
- ProcessStats.ServiceState ss = as.mServices.get(className);
- if (ss != null) {
- ss.makeActive();
- return ss;
- }
- final ProcessStats.ProcessState ps = mProcessStats.getProcessStateLocked(packageName,
- uid, processName);
- ss = new ProcessStats.ServiceState(mProcessStats, packageName, ps);
- as.mServices.put(className, ss);
- return ss;
+ return mProcessStats.getServiceStateLocked(packageName, uid, processName, className);
}
public boolean isMemFactorLowered() {
@@ -269,40 +261,11 @@ public final class ProcessStatsService extends IProcessStats.Stub {
}
}
- static byte[] readFully(FileInputStream stream) throws java.io.IOException {
- int pos = 0;
- int avail = stream.available();
- byte[] data = new byte[avail];
- while (true) {
- int amt = stream.read(data, pos, data.length-pos);
- //Log.i("foo", "Read " + amt + " bytes at " + pos
- // + " of avail " + data.length);
- if (amt <= 0) {
- //Log.i("foo", "**** FINISHED READING: pos=" + pos
- // + " len=" + data.length);
- return data;
- }
- pos += amt;
- avail = stream.available();
- if (avail > data.length-pos) {
- byte[] newData = new byte[pos+avail];
- System.arraycopy(data, 0, newData, 0, pos);
- data = newData;
- }
- }
- }
-
boolean readLocked(ProcessStats stats, AtomicFile file) {
try {
FileInputStream stream = file.openRead();
-
- byte[] raw = readFully(stream);
- Parcel in = Parcel.obtain();
- in.unmarshall(raw, 0, raw.length);
- in.setDataPosition(0);
+ stats.read(stream);
stream.close();
-
- stats.readFromParcel(in);
if (stats.mReadError != null) {
Slog.w(TAG, "Ignoring existing stats; " + stats.mReadError);
if (DEBUG) {
@@ -449,7 +412,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
Parcel current = Parcel.obtain();
mWriteLock.lock();
try {
- synchronized (mLock) {
+ synchronized (mAm) {
mProcessStats.writeToParcel(current, 0);
}
if (historic != null) {
@@ -493,7 +456,16 @@ public final class ProcessStatsService extends IProcessStats.Stub {
pw.println(" <package.name>: optional name of package to filter output by.");
}
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ @Override
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mAm.checkCallingPermission(android.Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump procstats from from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+ + " without permission " + android.Manifest.permission.DUMP);
+ return;
+ }
+
final long now = SystemClock.uptimeMillis();
boolean isCheckin = false;
@@ -638,7 +610,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
}
}
pw.println();
- synchronized (mLock) {
+ synchronized (mAm) {
dumpFilteredProcessesCsvLocked(pw, null,
csvSepScreenStats, csvScreenStats, csvSepMemStats, csvMemStats,
csvSepProcStats, csvProcStats, now, reqPackage);
@@ -721,7 +693,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
}
}
if (!isCheckin) {
- synchronized (mLock) {
+ synchronized (mAm) {
if (isCompact) {
mProcessStats.dumpCheckinLocked(pw, reqPackage);
} else {
diff --git a/services/java/com/android/server/display/DisplayManagerService.java b/services/java/com/android/server/display/DisplayManagerService.java
index 4b3463c..659163c 100644
--- a/services/java/com/android/server/display/DisplayManagerService.java
+++ b/services/java/com/android/server/display/DisplayManagerService.java
@@ -154,9 +154,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
// List of all currently connected display devices.
private final ArrayList<DisplayDevice> mDisplayDevices = new ArrayList<DisplayDevice>();
- // List of all removed display devices.
- private final ArrayList<DisplayDevice> mRemovedDisplayDevices = new ArrayList<DisplayDevice>();
-
// List of all logical displays indexed by logical display id.
private final SparseArray<LogicalDisplay> mLogicalDisplays =
new SparseArray<LogicalDisplay>();
@@ -798,7 +795,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
Slog.i(TAG, "Display device removed: " + device.getDisplayDeviceInfoLocked());
- mRemovedDisplayDevices.add(device);
updateLogicalDisplaysLocked();
scheduleTraversalLocked(false);
}
@@ -900,14 +896,6 @@ public final class DisplayManagerService extends IDisplayManager.Stub {
}
private void performTraversalInTransactionLocked() {
- // Perform one last traversal for each removed display device.
- final int removedCount = mRemovedDisplayDevices.size();
- for (int i = 0; i < removedCount; i++) {
- DisplayDevice device = mRemovedDisplayDevices.get(i);
- device.performTraversalInTransactionLocked();
- }
- mRemovedDisplayDevices.clear();
-
// Clear all viewports before configuring displays so that we can keep
// track of which ones we have configured.
clearViewportsLocked();
diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java
index ce402a5..007acf7 100644
--- a/services/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -211,11 +211,13 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
mSurfaceTexture = surfaceTexture;
}
- public void clearSurfaceTextureLocked() {
- if (mSurfaceTexture != null) {
- mSurfaceTexture = null;
+ public void destroyLocked() {
+ mSurfaceTexture = null;
+ if (mSurface != null) {
+ mSurface.release();
+ mSurface = null;
}
- sendTraversalRequestLocked();
+ SurfaceControl.destroyDisplay(getDisplayTokenLocked());
}
@Override
@@ -225,12 +227,6 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
mSurface = new Surface(mSurfaceTexture);
}
setSurfaceInTransactionLocked(mSurface);
- } else {
- setSurfaceInTransactionLocked(null);
- if (mSurface != null) {
- mSurface.destroy();
- mSurface = null;
- }
}
}
@@ -307,7 +303,7 @@ final class OverlayDisplayAdapter extends DisplayAdapter {
public void onWindowDestroyed() {
synchronized (getSyncRoot()) {
if (mDevice != null) {
- mDevice.clearSurfaceTextureLocked();
+ mDevice.destroyLocked();
sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_REMOVED);
}
}
diff --git a/services/java/com/android/server/display/VirtualDisplayAdapter.java b/services/java/com/android/server/display/VirtualDisplayAdapter.java
index 3a71361..46d473c 100644
--- a/services/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -58,7 +58,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
try {
appToken.linkToDeath(device, 0);
} catch (RemoteException ex) {
- device.releaseLocked();
+ device.destroyLocked();
return null;
}
@@ -72,6 +72,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
if (device != null) {
+ device.destroyLocked();
appToken.unlinkToDeath(device, 0);
}
@@ -85,6 +86,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
if (device != null) {
Slog.i(TAG, "Virtual display device released because application token died: "
+ device.mOwnerPackageName);
+ device.destroyLocked();
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED);
}
}
@@ -100,7 +102,6 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
private final int mDensityDpi;
private final int mFlags;
- private boolean mReleased;
private Surface mSurface;
private DisplayDeviceInfo mInfo;
@@ -122,24 +123,25 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
@Override
public void binderDied() {
synchronized (getSyncRoot()) {
- if (!mReleased) {
+ if (mSurface != null) {
handleBinderDiedLocked(mAppToken);
}
}
}
- public void releaseLocked() {
- mReleased = true;
- sendTraversalRequestLocked();
+ public void destroyLocked() {
+ if (mSurface != null) {
+ mSurface.release();
+ mSurface = null;
+ }
+ SurfaceControl.destroyDisplay(getDisplayTokenLocked());
}
@Override
public void performTraversalInTransactionLocked() {
- if (mReleased && mSurface != null) {
- mSurface.destroy();
- mSurface = null;
+ if (mSurface != null) {
+ setSurfaceInTransactionLocked(mSurface);
}
- setSurfaceInTransactionLocked(mSurface);
}
@Override
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index 11d3819..a9da30f 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -374,7 +374,7 @@ final class WifiDisplayAdapter extends DisplayAdapter {
private void removeDisplayDeviceLocked() {
if (mDisplayDevice != null) {
- mDisplayDevice.clearSurfaceLocked();
+ mDisplayDevice.destroyLocked();
sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_REMOVED);
mDisplayDevice = null;
@@ -633,9 +633,12 @@ final class WifiDisplayAdapter extends DisplayAdapter {
mSurface = surface;
}
- public void clearSurfaceLocked() {
- mSurface = null;
- sendTraversalRequestLocked();
+ public void destroyLocked() {
+ if (mSurface != null) {
+ mSurface.release();
+ mSurface = null;
+ }
+ SurfaceControl.destroyDisplay(getDisplayTokenLocked());
}
public void setNameLocked(String name) {
@@ -645,7 +648,9 @@ final class WifiDisplayAdapter extends DisplayAdapter {
@Override
public void performTraversalInTransactionLocked() {
- setSurfaceInTransactionLocked(mSurface);
+ if (mSurface != null) {
+ setSurfaceInTransactionLocked(mSurface);
+ }
}
@Override
diff --git a/services/java/com/android/server/location/FlpHardwareProvider.java b/services/java/com/android/server/location/FlpHardwareProvider.java
new file mode 100644
index 0000000..469f7ce
--- /dev/null
+++ b/services/java/com/android/server/location/FlpHardwareProvider.java
@@ -0,0 +1,344 @@
+/*
+ * 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 com.android.server.location;
+
+import android.hardware.location.GeofenceHardwareImpl;
+import android.hardware.location.IFusedLocationHardware;
+import android.hardware.location.IFusedLocationHardwareSink;
+import android.location.IFusedGeofenceHardware;
+import android.location.FusedBatchOptions;
+import android.location.Geofence;
+import android.location.Location;
+import android.location.LocationListener;
+import android.location.LocationManager;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.Slog;
+
+/**
+ * This class is an interop layer for JVM types and the JNI code that interacts
+ * with the FLP HAL implementation.
+ *
+ * {@hide}
+ */
+public class FlpHardwareProvider {
+ private GeofenceHardwareImpl mGeofenceHardwareSink = null;
+ private IFusedLocationHardwareSink mLocationSink = null;
+
+ private static FlpHardwareProvider sSingletonInstance = null;
+
+ private final static String TAG = "FlpHardwareProvider";
+ private final Context mContext;
+
+ public static FlpHardwareProvider getInstance(Context context) {
+ if (sSingletonInstance == null) {
+ sSingletonInstance = new FlpHardwareProvider(context);
+ }
+
+ return sSingletonInstance;
+ }
+
+ private FlpHardwareProvider(Context context) {
+ mContext = context;
+
+ // register for listening for passive provider data
+ Handler handler = new Handler();
+ LocationManager manager = (LocationManager) mContext.getSystemService(
+ Context.LOCATION_SERVICE);
+ manager.requestLocationUpdates(
+ LocationManager.PASSIVE_PROVIDER,
+ 0 /* minTime */,
+ 0 /* minDistance */,
+ new NetworkLocationListener(),
+ handler.getLooper());
+ }
+
+ public static boolean isSupported() {
+ return nativeIsSupported();
+ }
+
+ /**
+ * Private callback functions used by FLP HAL.
+ */
+ // FlpCallbacks members
+ private void onLocationReport(Location[] locations) {
+ for (Location location : locations) {
+ location.setProvider(LocationManager.FUSED_PROVIDER);
+ // set the elapsed time-stamp just as GPS provider does
+ location.setElapsedRealtimeNanos(SystemClock.elapsedRealtimeNanos());
+ }
+
+ try {
+ if (mLocationSink != null) {
+ mLocationSink.onLocationAvailable(locations);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException calling onLocationAvailable");
+ }
+ }
+
+ // FlpDiagnosticCallbacks members
+ private void onDataReport(String data) {
+ try {
+ if (mLocationSink != null) {
+ mLocationSink.onDiagnosticDataAvailable(data);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException calling onDiagnosticDataAvailable");
+ }
+ }
+
+ // FlpGeofenceCallbacks members
+ private void onGeofenceTransition(
+ int geofenceId,
+ Location location,
+ int transition,
+ long timestamp,
+ int sourcesUsed
+ ) {
+ // TODO: [GeofenceIntegration] change GeofenceHardwareImpl to accept a location object
+ }
+
+ private void onGeofenceMonitorStatus(int status, int source, Location location) {
+ // TODO: [GeofenceIntegration]
+ }
+
+ private void onGeofenceAdd(int geofenceId, int result) {
+ // TODO: [GeofenceIntegration] map between GPS and FLP results to pass a consistent status
+ }
+
+ private void onGeofenceRemove(int geofenceId, int result) {
+ // TODO: [GeofenceIntegration] map between GPS and FLP results to pass a consistent status
+ }
+
+ private void onGeofencePause(int geofenceId, int result) {
+ // TODO; [GeofenceIntegration] map between GPS and FLP results
+ }
+
+ private void onGeofenceResume(int geofenceId, int result) {
+ // TODO: [GeofenceIntegration] map between GPS and FLP results
+ }
+
+ /**
+ * Private native methods accessing FLP HAL.
+ */
+ static { nativeClassInit(); }
+
+ // Core members
+ private static native void nativeClassInit();
+ private static native boolean nativeIsSupported();
+
+ // FlpLocationInterface members
+ private native void nativeInit();
+ private native int nativeGetBatchSize();
+ private native void nativeStartBatching(int requestId, FusedBatchOptions options);
+ private native void nativeUpdateBatchingOptions(int requestId, FusedBatchOptions optionsObject);
+ private native void nativeStopBatching(int id);
+ private native void nativeRequestBatchedLocation(int lastNLocations);
+ private native void nativeInjectLocation(Location location);
+ // TODO [Fix] sort out the lifetime of the instance
+ private native void nativeCleanup();
+
+ // FlpDiagnosticsInterface members
+ private native boolean nativeIsDiagnosticSupported();
+ private native void nativeInjectDiagnosticData(String data);
+
+ // FlpDeviceContextInterface members
+ private native boolean nativeIsDeviceContextSupported();
+ private native void nativeInjectDeviceContext(int deviceEnabledContext);
+
+ // FlpGeofencingInterface members
+ private native boolean nativeIsGeofencingSupported();
+ private native void nativeAddGeofences(int[] geofenceIdsArray, Geofence[] geofencesArray);
+ private native void nativePauseGeofence(int geofenceId);
+ private native void nativeResumeGeofence(int geofenceId, int monitorTransitions);
+ private native void nativeModifyGeofenceOption(
+ int geofenceId,
+ int lastTransition,
+ int monitorTransitions,
+ int notificationResponsiveness,
+ int unknownTimer,
+ int sourcesToUse);
+ private native void nativeRemoveGeofences(int[] geofenceIdsArray);
+
+ /**
+ * Interface implementations for services built on top of this functionality.
+ */
+ public static final String LOCATION = "Location";
+ public static final String GEOFENCING = "Geofencing";
+
+ public IFusedLocationHardware getLocationHardware() {
+ nativeInit();
+ return mLocationHardware;
+ }
+
+ public IFusedGeofenceHardware getGeofenceHardware() {
+ nativeInit();
+ return mGeofenceHardwareService;
+ }
+
+ private final IFusedLocationHardware mLocationHardware = new IFusedLocationHardware.Stub() {
+ @Override
+ public void registerSink(IFusedLocationHardwareSink eventSink) {
+ // only one sink is allowed at the moment
+ if (mLocationSink != null) {
+ throw new RuntimeException("IFusedLocationHardware does not support multiple sinks");
+ }
+
+ mLocationSink = eventSink;
+ }
+
+ @Override
+ public void unregisterSink(IFusedLocationHardwareSink eventSink) {
+ // don't throw if the sink is not registered, simply make it a no-op
+ if (mLocationSink == eventSink) {
+ mLocationSink = null;
+ }
+ }
+
+ @Override
+ public int getSupportedBatchSize() {
+ return nativeGetBatchSize();
+ }
+
+ @Override
+ public void startBatching(int requestId, FusedBatchOptions options) {
+ nativeStartBatching(requestId, options);
+ }
+
+ @Override
+ public void stopBatching(int requestId) {
+ nativeStopBatching(requestId);
+ }
+
+ @Override
+ public void updateBatchingOptions(int requestId, FusedBatchOptions options) {
+ nativeUpdateBatchingOptions(requestId, options);
+ }
+
+ @Override
+ public void requestBatchOfLocations(int batchSizeRequested) {
+ nativeRequestBatchedLocation(batchSizeRequested);
+ }
+
+ @Override
+ public boolean supportsDiagnosticDataInjection() {
+ return nativeIsDiagnosticSupported();
+ }
+
+ @Override
+ public void injectDiagnosticData(String data) {
+ nativeInjectDiagnosticData(data);
+ }
+
+ @Override
+ public boolean supportsDeviceContextInjection() {
+ return nativeIsDeviceContextSupported();
+ }
+
+ @Override
+ public void injectDeviceContext(int deviceEnabledContext) {
+ nativeInjectDeviceContext(deviceEnabledContext);
+ }
+ };
+
+ private final IFusedGeofenceHardware mGeofenceHardwareService =
+ new IFusedGeofenceHardware.Stub() {
+ @Override
+ public boolean isSupported() {
+ return nativeIsGeofencingSupported();
+ }
+
+ @Override
+ public void addGeofences(int[] geofenceIdsArray, Geofence[] geofencesArray) {
+ nativeAddGeofences(geofenceIdsArray, geofencesArray);
+ }
+
+ @Override
+ public void removeGeofences(int[] geofenceIds) {
+ nativeRemoveGeofences(geofenceIds);
+ }
+
+ @Override
+ public void pauseMonitoringGeofence(int geofenceId) {
+ nativePauseGeofence(geofenceId);
+ }
+
+ @Override
+ public void resumeMonitoringGeofence(int geofenceId, int monitorTransitions) {
+ nativeResumeGeofence(geofenceId, monitorTransitions);
+ }
+
+ @Override
+ public void modifyGeofenceOptions(int geofenceId,
+ int lastTransition,
+ int monitorTransitions,
+ int notificationResponsiveness,
+ int unknownTimer
+ ) {
+ // TODO: [GeofenceIntegration] set sourcesToUse to the right value
+ // TODO: expose sourcesToUse externally when needed
+ nativeModifyGeofenceOption(
+ geofenceId,
+ lastTransition,
+ monitorTransitions,
+ notificationResponsiveness,
+ unknownTimer,
+ /* sourcesToUse */ 0xFFFF);
+ }
+ };
+
+ /**
+ * Internal classes and functions used by the provider.
+ */
+ private final class NetworkLocationListener implements LocationListener {
+ @Override
+ public void onLocationChanged(Location location) {
+ if (
+ !LocationManager.NETWORK_PROVIDER.equals(location.getProvider()) ||
+ !location.hasAccuracy()
+ ) {
+ return;
+ }
+
+ nativeInjectLocation(location);
+ }
+
+ @Override
+ public void onStatusChanged(String provider, int status, Bundle extras) { }
+
+ @Override
+ public void onProviderEnabled(String provider) { }
+
+ @Override
+ public void onProviderDisabled(String provider) { }
+ }
+
+ private GeofenceHardwareImpl getGeofenceHardwareSink() {
+ if (mGeofenceHardwareSink == null) {
+ // TODO: [GeofenceIntegration] we need to register ourselves with GeofenceHardwareImpl
+ mGeofenceHardwareSink = GeofenceHardwareImpl.getInstance(mContext);
+ }
+
+ return mGeofenceHardwareSink;
+ }
+} \ No newline at end of file
diff --git a/services/java/com/android/server/location/FusedLocationHardwareSecure.java b/services/java/com/android/server/location/FusedLocationHardwareSecure.java
new file mode 100644
index 0000000..389bd24
--- /dev/null
+++ b/services/java/com/android/server/location/FusedLocationHardwareSecure.java
@@ -0,0 +1,119 @@
+/*
+ * 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 com.android.server.location;
+
+import android.content.Context;
+import android.hardware.location.IFusedLocationHardware;
+import android.hardware.location.IFusedLocationHardwareSink;
+import android.location.FusedBatchOptions;
+import android.os.RemoteException;
+
+/**
+ * FusedLocationHardware decorator that adds permission checking.
+ * @hide
+ */
+public class FusedLocationHardwareSecure extends IFusedLocationHardware.Stub {
+ private final IFusedLocationHardware mLocationHardware;
+ private final Context mContext;
+ private final String mPermissionId;
+
+ public FusedLocationHardwareSecure(
+ IFusedLocationHardware locationHardware,
+ Context context,
+ String permissionId) {
+ mLocationHardware = locationHardware;
+ mContext = context;
+ mPermissionId = permissionId;
+ }
+
+ private void checkPermissions() {
+ mContext.enforceCallingPermission(
+ mPermissionId,
+ String.format(
+ "Permission '%s' not granted to access FusedLocationHardware",
+ mPermissionId));
+ }
+
+ @Override
+ public void registerSink(IFusedLocationHardwareSink eventSink) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.registerSink(eventSink);
+ }
+
+ @Override
+ public void unregisterSink(IFusedLocationHardwareSink eventSink) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.unregisterSink(eventSink);
+ }
+
+ @Override
+ public int getSupportedBatchSize() throws RemoteException {
+ checkPermissions();
+ return mLocationHardware.getSupportedBatchSize();
+ }
+
+ @Override
+ public void startBatching(int id, FusedBatchOptions batchOptions) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.startBatching(id, batchOptions);
+ }
+
+ @Override
+ public void stopBatching(int id) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.stopBatching(id);
+ }
+
+ @Override
+ public void updateBatchingOptions(
+ int id,
+ FusedBatchOptions batchoOptions
+ ) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.updateBatchingOptions(id, batchoOptions);
+ }
+
+ @Override
+ public void requestBatchOfLocations(int batchSizeRequested) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.requestBatchOfLocations(batchSizeRequested);
+ }
+
+ @Override
+ public boolean supportsDiagnosticDataInjection() throws RemoteException {
+ checkPermissions();
+ return mLocationHardware.supportsDiagnosticDataInjection();
+ }
+
+ @Override
+ public void injectDiagnosticData(String data) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.injectDiagnosticData(data);
+ }
+
+ @Override
+ public boolean supportsDeviceContextInjection() throws RemoteException {
+ checkPermissions();
+ return mLocationHardware.supportsDeviceContextInjection();
+ }
+
+ @Override
+ public void injectDeviceContext(int deviceEnabledContext) throws RemoteException {
+ checkPermissions();
+ mLocationHardware.injectDeviceContext(deviceEnabledContext);
+ }
+}
diff --git a/services/java/com/android/server/location/FusedProxy.java b/services/java/com/android/server/location/FusedProxy.java
new file mode 100644
index 0000000..8278b96
--- /dev/null
+++ b/services/java/com/android/server/location/FusedProxy.java
@@ -0,0 +1,116 @@
+/*
+ * 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 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 com.android.server.location;
+
+import com.android.server.ServiceWatcher;
+
+import android.Manifest;
+import android.content.Context;
+import android.hardware.location.IFusedLocationHardware;
+import android.location.IFusedProvider;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * Proxy that helps bind GCore FusedProvider implementations to the Fused Hardware instances.
+ *
+ * @hide
+ */
+public final class FusedProxy {
+ private final String TAG = "FusedProxy";
+
+ private ServiceWatcher mServiceWatcher;
+
+ private FusedLocationHardwareSecure mLocationHardware;
+
+ /**
+ * Constructor of the class.
+ * This is private as the class follows a factory pattern for construction.
+ *
+ * @param context The context needed for construction.
+ * @param handler The handler needed for construction.
+ * @param locationHardware The instance of the Fused location hardware assigned to the proxy.
+ */
+ private FusedProxy(Context context, Handler handler, IFusedLocationHardware locationHardware) {
+ mLocationHardware = new FusedLocationHardwareSecure(
+ locationHardware,
+ context,
+ Manifest.permission.LOCATION_HARDWARE);
+ Runnable newServiceWork = new Runnable() {
+ @Override
+ public void run() {
+ bindProvider(mLocationHardware);
+ }
+ };
+
+ // prepare the connection to the provider
+ mServiceWatcher = new ServiceWatcher(
+ context,
+ TAG,
+ "com.android.location.service.FusedProvider",
+ com.android.internal.R.bool.config_enableFusedLocationOverlay,
+ com.android.internal.R.string.config_fusedLocationProviderPackageName,
+ com.android.internal.R.array.config_locationProviderPackageNames,
+ newServiceWork,
+ handler);
+ }
+
+ /**
+ * Creates an instance of the proxy and binds it to the appropriate FusedProvider.
+ *
+ * @param context The context needed for construction.
+ * @param handler The handler needed for construction.
+ * @param locationHardware The instance of the Fused location hardware assigned to the proxy.
+ *
+ * @return An instance of the proxy if it could be bound, null otherwise.
+ */
+ public static FusedProxy createAndBind(
+ Context context,
+ Handler handler,
+ IFusedLocationHardware locationHardware
+ ) {
+ FusedProxy fusedProxy = new FusedProxy(context, handler, locationHardware);
+
+ // try to bind the Fused provider
+ if (!fusedProxy.mServiceWatcher.start()) {
+ return null;
+ }
+
+ return fusedProxy;
+ }
+
+ /**
+ * Helper function to bind the FusedLocationHardware to the appropriate FusedProvider instance.
+ *
+ * @param locationHardware The FusedLocationHardware instance to use for the binding operation.
+ */
+ private void bindProvider(IFusedLocationHardware locationHardware) {
+ IFusedProvider provider = IFusedProvider.Stub.asInterface(mServiceWatcher.getBinder());
+
+ if (provider == null) {
+ Log.e(TAG, "No instance of FusedProvider found on FusedLocationHardware connected.");
+ return;
+ }
+
+ try {
+ provider.onFusedLocationHardwareChange(locationHardware);
+ } catch (RemoteException e) {
+ Log.e(TAG, e.toString());
+ }
+ }
+}
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 163536a..e78362b 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -22,6 +22,8 @@ import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
+import static android.os.Process.SYSTEM_UID;
+import static android.os.Process.PACKAGE_INFO_GID;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
@@ -117,6 +119,7 @@ final class Settings {
private final File mPackageListFilename;
private final File mStoppedPackagesFilename;
private final File mBackupStoppedPackagesFilename;
+
final HashMap<String, PackageSetting> mPackages =
new HashMap<String, PackageSetting>();
// List of replaced system applications
@@ -201,6 +204,8 @@ final class Settings {
mSettingsFilename = new File(mSystemDir, "packages.xml");
mBackupSettingsFilename = new File(mSystemDir, "packages-backup.xml");
mPackageListFilename = new File(mSystemDir, "packages.list");
+ FileUtils.setPermissions(mPackageListFilename, 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
// Deprecated: Needed for migration
mStoppedPackagesFilename = new File(mSystemDir, "packages-stopped.xml");
mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml");
@@ -1369,13 +1374,15 @@ final class Settings {
-1, -1);
// Write package list file now, use a JournaledFile.
- //
- File tempFile = new File(mPackageListFilename.toString() + ".tmp");
+ File tempFile = new File(mPackageListFilename.getAbsolutePath() + ".tmp");
JournaledFile journal = new JournaledFile(mPackageListFilename, tempFile);
- fstr = new FileOutputStream(journal.chooseForWrite());
+ final File writeTarget = journal.chooseForWrite();
+ fstr = new FileOutputStream(writeTarget);
str = new BufferedOutputStream(fstr);
try {
+ FileUtils.setPermissions(fstr.getFD(), 0660, SYSTEM_UID, PACKAGE_INFO_GID);
+
StringBuilder sb = new StringBuilder();
for (final PackageSetting pkg : mPackages.values()) {
ApplicationInfo ai = pkg.pkg.applicationInfo;
@@ -1400,6 +1407,7 @@ final class Settings {
// DO NOT MODIFY THIS FORMAT UNLESS YOU CAN ALSO MODIFY ITS USERS
// FROM NATIVE CODE. AT THE MOMENT, LOOK AT THE FOLLOWING SOURCES:
// system/core/run-as/run-as.c
+ // system/core/sdcard/sdcard.c
//
sb.setLength(0);
sb.append(ai.packageName);
@@ -1421,11 +1429,6 @@ final class Settings {
journal.rollback();
}
- FileUtils.setPermissions(mPackageListFilename.toString(),
- FileUtils.S_IRUSR|FileUtils.S_IWUSR
- |FileUtils.S_IRGRP|FileUtils.S_IWGRP,
- -1, -1);
-
writeAllUsersPackageRestrictionsLPr();
return;
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index 3946f15..93d8e07 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -15,6 +15,7 @@ LOCAL_SRC_FILES:= \
com_android_server_UsbHostManager.cpp \
com_android_server_VibratorService.cpp \
com_android_server_location_GpsLocationProvider.cpp \
+ com_android_server_location_FlpHardwareProvider.cpp \
com_android_server_connectivity_Vpn.cpp \
onload.cpp
diff --git a/services/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/jni/com_android_server_location_FlpHardwareProvider.cpp
new file mode 100644
index 0000000..48b86db
--- /dev/null
+++ b/services/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -0,0 +1,901 @@
+/*
+ * 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/license/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.
+ */
+
+#define LOG_TAG "FuseLocationProvider"
+#define LOG_NDEBUG 0
+
+#define WAKE_LOCK_NAME "FLP"
+#define LOCATION_CLASS_NAME "android/location/Location"
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+#include "hardware/fused_location.h"
+#include "hardware_legacy/power.h"
+
+static jobject sCallbacksObj = NULL;
+static JNIEnv *sCallbackEnv = NULL;
+static hw_device_t* sHardwareDevice = NULL;
+
+static jmethodID sOnLocationReport = NULL;
+static jmethodID sOnDataReport = NULL;
+static jmethodID sOnGeofenceTransition = NULL;
+static jmethodID sOnGeofenceMonitorStatus = NULL;
+static jmethodID sOnGeofenceAdd = NULL;
+static jmethodID sOnGeofenceRemove = NULL;
+static jmethodID sOnGeofencePause = NULL;
+static jmethodID sOnGeofenceResume = NULL;
+
+static const FlpLocationInterface* sFlpInterface = NULL;
+static const FlpDiagnosticInterface* sFlpDiagnosticInterface = NULL;
+static const FlpGeofencingInterface* sFlpGeofencingInterface = NULL;
+static const FlpDeviceContextInterface* sFlpDeviceContextInterface = NULL;
+
+namespace android {
+
+static inline void CheckExceptions(JNIEnv* env, const char* methodName) {
+ if(!env->ExceptionCheck()) {
+ return;
+ }
+
+ ALOGE("An exception was thrown by '%s'.", methodName);
+ LOGE_EX(env);
+ env->ExceptionClear();
+}
+
+static inline void ThrowOnError(
+ JNIEnv* env,
+ int resultCode,
+ const char* methodName) {
+ if(resultCode == FLP_RESULT_SUCCESS) {
+ return;
+ }
+
+ ALOGE("Error %d in '%s'", resultCode, methodName);
+ jclass exceptionClass = env->FindClass("java/lang/RuntimeException");
+ env->ThrowNew(exceptionClass, methodName);
+}
+
+static bool IsValidCallbackThread() {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ if(sCallbackEnv == NULL || sCallbackEnv != env) {
+ ALOGE("CallbackThread check fail: env=%p, expected=%p", env, sCallbackEnv);
+ return false;
+ }
+
+ return true;
+}
+
+static int SetThreadEvent(ThreadEvent event) {
+ JavaVM* javaVm = AndroidRuntime::getJavaVM();
+
+ switch(event) {
+ case ASSOCIATE_JVM:
+ {
+ if(sCallbackEnv != NULL) {
+ ALOGE(
+ "Attempted to associate callback in '%s'. Callback already associated.",
+ __FUNCTION__
+ );
+ return FLP_RESULT_ERROR;
+ }
+
+ JavaVMAttachArgs args = {
+ JNI_VERSION_1_6,
+ "FLP Service Callback Thread",
+ /* group */ NULL
+ };
+
+ jint attachResult = javaVm->AttachCurrentThread(&sCallbackEnv, &args);
+ if (attachResult != 0) {
+ ALOGE("Callback thread attachment error: %d", attachResult);
+ return FLP_RESULT_ERROR;
+ }
+
+ ALOGV("Callback thread attached: %p", sCallbackEnv);
+ break;
+ }
+ case DISASSOCIATE_JVM:
+ {
+ if (!IsValidCallbackThread()) {
+ ALOGE(
+ "Attempted to dissasociate an unnownk callback thread : '%s'.",
+ __FUNCTION__
+ );
+ return FLP_RESULT_ERROR;
+ }
+
+ if (javaVm->DetachCurrentThread() != 0) {
+ return FLP_RESULT_ERROR;
+ }
+
+ sCallbackEnv = NULL;
+ break;
+ }
+ default:
+ ALOGE("Invalid ThreadEvent request %d", event);
+ return FLP_RESULT_ERROR;
+ }
+
+ return FLP_RESULT_SUCCESS;
+}
+
+/*
+ * Initializes the FlpHardwareProvider class from the native side by opening
+ * the HW module and obtaining the proper interfaces.
+ */
+static void ClassInit(JNIEnv* env, jclass clazz) {
+ // get references to the Java provider methods
+ sOnLocationReport = env->GetMethodID(
+ clazz,
+ "onLocationReport",
+ "([Landroid/location/Location;)V");
+ sOnDataReport = env->GetMethodID(
+ clazz,
+ "onDataReport",
+ "(Ljava/lang/String;)V"
+ );
+ sOnGeofenceTransition = env->GetMethodID(
+ clazz,
+ "onGeofenceTransition",
+ "(ILandroid/location/Location;IJI)V"
+ );
+ sOnGeofenceMonitorStatus = env->GetMethodID(
+ clazz,
+ "onGeofenceMonitorStatus",
+ "(IILandroid/location/Location;)V"
+ );
+ sOnGeofenceAdd = env->GetMethodID(clazz, "onGeofenceAdd", "(II)V");
+ sOnGeofenceRemove = env->GetMethodID(clazz, "onGeofenceRemove", "(II)V");
+ sOnGeofencePause = env->GetMethodID(clazz, "onGeofencePause", "(II)V");
+ sOnGeofenceResume = env->GetMethodID(clazz, "onGeofenceResume", "(II)V");
+}
+
+/*
+ * Helper function to unwrap a java object back into a FlpLocation structure.
+ */
+static void TranslateFromObject(
+ JNIEnv* env,
+ jobject locationObject,
+ FlpLocation& location) {
+ location.size = sizeof(FlpLocation);
+ location.flags = 0;
+
+ jclass locationClass = env->GetObjectClass(locationObject);
+
+ jmethodID getLatitude = env->GetMethodID(locationClass, "getLatitude", "()D");
+ location.latitude = env->CallDoubleMethod(locationObject, getLatitude);
+ jmethodID getLongitude = env->GetMethodID(locationClass, "getLongitude", "()D");
+ location.longitude = env->CallDoubleMethod(locationObject, getLongitude);
+ jmethodID getTime = env->GetMethodID(locationClass, "getTime", "()J");
+ location.timestamp = env->CallLongMethod(locationObject, getTime);
+ location.flags |= FLP_LOCATION_HAS_LAT_LONG;
+
+ jmethodID hasAltitude = env->GetMethodID(locationClass, "hasAltitude", "()Z");
+ if (env->CallBooleanMethod(locationObject, hasAltitude)) {
+ jmethodID getAltitude = env->GetMethodID(locationClass, "getAltitude", "()D");
+ location.altitude = env->CallDoubleMethod(locationObject, getAltitude);
+ location.flags |= FLP_LOCATION_HAS_ALTITUDE;
+ }
+
+ jmethodID hasSpeed = env->GetMethodID(locationClass, "hasSpeed", "()Z");
+ if (env->CallBooleanMethod(locationObject, hasSpeed)) {
+ jmethodID getSpeed = env->GetMethodID(locationClass, "getSpeed", "()F");
+ location.speed = env->CallFloatMethod(locationObject, getSpeed);
+ location.flags |= FLP_LOCATION_HAS_SPEED;
+ }
+
+ jmethodID hasBearing = env->GetMethodID(locationClass, "hasBearing", "()Z");
+ if (env->CallBooleanMethod(locationObject, hasBearing)) {
+ jmethodID getBearing = env->GetMethodID(locationClass, "getBearing", "()F");
+ location.bearing = env->CallFloatMethod(locationObject, getBearing);
+ location.flags |= FLP_LOCATION_HAS_BEARING;
+ }
+
+ jmethodID hasAccuracy = env->GetMethodID(locationClass, "hasAccuracy", "()Z");
+ if (env->CallBooleanMethod(locationObject, hasAccuracy)) {
+ jmethodID getAccuracy = env->GetMethodID(
+ locationClass,
+ "getAccuracy",
+ "()F"
+ );
+ location.accuracy = env->CallFloatMethod(locationObject, getAccuracy);
+ location.flags |= FLP_LOCATION_HAS_ACCURACY;
+ }
+
+ // TODO: wire sources_used if Location class exposes them
+}
+
+/*
+ * Helper function to unwrap FlpBatchOptions from the Java Runtime calls.
+ */
+static void TranslateFromObject(
+ JNIEnv* env,
+ jobject batchOptionsObject,
+ FlpBatchOptions& batchOptions) {
+ jclass batchOptionsClass = env->GetObjectClass(batchOptionsObject);
+
+ jmethodID getMaxPower = env->GetMethodID(
+ batchOptionsClass,
+ "getMaxPowerAllocationInMW",
+ "()D"
+ );
+ batchOptions.max_power_allocation_mW = env->CallDoubleMethod(
+ batchOptionsObject,
+ getMaxPower
+ );
+
+ jmethodID getPeriod = env->GetMethodID(
+ batchOptionsClass,
+ "getPeriodInNS",
+ "()J"
+ );
+ batchOptions.period_ns = env->CallLongMethod(batchOptionsObject, getPeriod);
+
+ jmethodID getSourcesToUse = env->GetMethodID(
+ batchOptionsClass,
+ "getSourcesToUse",
+ "()I"
+ );
+ batchOptions.sources_to_use = env->CallIntMethod(
+ batchOptionsObject,
+ getSourcesToUse
+ );
+
+ jmethodID getFlags = env->GetMethodID(batchOptionsClass, "getFlags", "()I");
+ batchOptions.flags = env->CallIntMethod(batchOptionsObject, getFlags);
+}
+
+/*
+ * Helper function to transform FlpLocation into a java object.
+ */
+static void TranslateToObject(const FlpLocation* location, jobject& locationObject) {
+ jclass locationClass = sCallbackEnv->FindClass(LOCATION_CLASS_NAME);
+ jmethodID locationCtor = sCallbackEnv->GetMethodID(
+ locationClass,
+ "<init>",
+ "(Ljava/lang/String;)V"
+ );
+
+ // the provider is set in the upper JVM layer
+ locationObject = sCallbackEnv->NewObject(locationClass, locationCtor, NULL);
+ jint flags = location->flags;
+
+ // set the valid information in the object
+ if (flags & FLP_LOCATION_HAS_LAT_LONG) {
+ jmethodID setLatitude = sCallbackEnv->GetMethodID(
+ locationClass,
+ "setLatitude",
+ "(D)V"
+ );
+ sCallbackEnv->CallVoidMethod(locationObject, setLatitude, location->latitude);
+
+ jmethodID setLongitude = sCallbackEnv->GetMethodID(
+ locationClass,
+ "setLongitude",
+ "(D)V"
+ );
+ sCallbackEnv->CallVoidMethod(
+ locationObject,
+ setLongitude,
+ location->longitude
+ );
+
+ jmethodID setTime = sCallbackEnv->GetMethodID(
+ locationClass,
+ "setTime",
+ "(J)V"
+ );
+ sCallbackEnv->CallVoidMethod(locationObject, setTime, location->timestamp);
+ }
+
+ if (flags & FLP_LOCATION_HAS_ALTITUDE) {
+ jmethodID setAltitude = sCallbackEnv->GetMethodID(
+ locationClass,
+ "setAltitude",
+ "(D)V"
+ );
+ sCallbackEnv->CallVoidMethod(locationObject, setAltitude, location->altitude);
+ }
+
+ if (flags & FLP_LOCATION_HAS_SPEED) {
+ jmethodID setSpeed = sCallbackEnv->GetMethodID(
+ locationClass,
+ "setSpeed",
+ "(F)V"
+ );
+ sCallbackEnv->CallVoidMethod(locationObject, setSpeed, location->speed);
+ }
+
+ if (flags & FLP_LOCATION_HAS_BEARING) {
+ jmethodID setBearing = sCallbackEnv->GetMethodID(
+ locationClass,
+ "setBearing",
+ "(F)V"
+ );
+ sCallbackEnv->CallVoidMethod(locationObject, setBearing, location->bearing);
+ }
+
+ if (flags & FLP_LOCATION_HAS_ACCURACY) {
+ jmethodID setAccuracy = sCallbackEnv->GetMethodID(
+ locationClass,
+ "setAccuracy",
+ "(F)V"
+ );
+ sCallbackEnv->CallVoidMethod(locationObject, setAccuracy, location->accuracy);
+ }
+
+ // TODO: wire FlpLocation::sources_used when needed
+}
+
+/*
+ * Helper function to serialize FlpLocation structures.
+ */
+static void TranslateToObjectArray(
+ int32_t locationsCount,
+ FlpLocation** locations,
+ jobjectArray& locationsArray) {
+ jclass locationClass = sCallbackEnv->FindClass(LOCATION_CLASS_NAME);
+ locationsArray = sCallbackEnv->NewObjectArray(
+ locationsCount,
+ locationClass,
+ /* initialElement */ NULL
+ );
+
+ for (int i = 0; i < locationsCount; ++i) {
+ jobject locationObject = NULL;
+ TranslateToObject(locations[i], locationObject);
+ sCallbackEnv->SetObjectArrayElement(locationsArray, i, locationObject);
+ sCallbackEnv->DeleteLocalRef(locationObject);
+ }
+}
+
+static void LocationCallback(int32_t locationsCount, FlpLocation** locations) {
+ if(!IsValidCallbackThread()) {
+ return;
+ }
+
+ if(locationsCount == 0 || locations == NULL) {
+ ALOGE(
+ "Invalid LocationCallback. Count: %d, Locations: %p",
+ locationsCount,
+ locations
+ );
+ return;
+ }
+
+ jobjectArray locationsArray = NULL;
+ TranslateToObjectArray(locationsCount, locations, locationsArray);
+
+ sCallbackEnv->CallVoidMethod(
+ sCallbacksObj,
+ sOnLocationReport,
+ locationsArray
+ );
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+static void AcquireWakelock() {
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
+}
+
+static void ReleaseWakelock() {
+ release_wake_lock(WAKE_LOCK_NAME);
+}
+
+FlpCallbacks sFlpCallbacks = {
+ sizeof(FlpCallbacks),
+ LocationCallback,
+ AcquireWakelock,
+ ReleaseWakelock,
+ SetThreadEvent
+};
+
+static void ReportData(char* data, int length) {
+ jstring stringData = NULL;
+
+ if(length != 0 && data != NULL) {
+ stringData = sCallbackEnv->NewString(reinterpret_cast<jchar*>(data), length);
+ } else {
+ ALOGE("Invalid ReportData callback. Length: %d, Data: %p", length, data);
+ return;
+ }
+
+ sCallbackEnv->CallVoidMethod(sCallbacksObj, sOnDataReport, stringData);
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+FlpDiagnosticCallbacks sFlpDiagnosticCallbacks = {
+ sizeof(FlpDiagnosticCallbacks),
+ SetThreadEvent,
+ ReportData
+};
+
+static void GeofenceTransitionCallback(
+ int32_t geofenceId,
+ FlpLocation* location,
+ int32_t transition,
+ FlpUtcTime timestamp,
+ uint32_t sourcesUsed
+ ) {
+ if(!IsValidCallbackThread()) {
+ return;
+ }
+
+ if(location == NULL) {
+ ALOGE("GeofenceTransition received with invalid location: %p", location);
+ return;
+ }
+
+ jobject locationObject = NULL;
+ TranslateToObject(location, locationObject);
+
+ sCallbackEnv->CallVoidMethod(
+ sCallbacksObj,
+ sOnGeofenceTransition,
+ geofenceId,
+ locationObject,
+ transition,
+ timestamp,
+ sourcesUsed
+ );
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+static void GeofenceMonitorStatusCallback(
+ int32_t status,
+ uint32_t source,
+ FlpLocation* lastLocation) {
+ if(!IsValidCallbackThread()) {
+ return;
+ }
+
+ jobject locationObject = NULL;
+ if(lastLocation != NULL) {
+ TranslateToObject(lastLocation, locationObject);
+ }
+
+ sCallbackEnv->CallVoidMethod(
+ sCallbacksObj,
+ sOnGeofenceMonitorStatus,
+ status,
+ source,
+ locationObject
+ );
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+static void GeofenceAddCallback(int32_t geofenceId, int32_t result) {
+ if(!IsValidCallbackThread()) {
+ return;
+ }
+
+ sCallbackEnv->CallVoidMethod(sCallbacksObj, sOnGeofenceAdd, geofenceId, result);
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+static void GeofenceRemoveCallback(int32_t geofenceId, int32_t result) {
+ if(!IsValidCallbackThread()) {
+ return;
+ }
+
+ sCallbackEnv->CallVoidMethod(
+ sCallbacksObj,
+ sOnGeofenceRemove,
+ geofenceId,
+ result
+ );
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+static void GeofencePauseCallback(int32_t geofenceId, int32_t result) {
+ if(!IsValidCallbackThread()) {
+ return;
+ }
+
+ sCallbackEnv->CallVoidMethod(
+ sCallbacksObj,
+ sOnGeofencePause,
+ geofenceId,
+ result
+ );
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+static void GeofenceResumeCallback(int32_t geofenceId, int32_t result) {
+ if(!IsValidCallbackThread()) {
+ return;
+ }
+
+ sCallbackEnv->CallVoidMethod(
+ sCallbacksObj,
+ sOnGeofenceResume,
+ geofenceId,
+ result
+ );
+ CheckExceptions(sCallbackEnv, __FUNCTION__);
+}
+
+FlpGeofenceCallbacks sFlpGeofenceCallbacks = {
+ sizeof(FlpGeofenceCallbacks),
+ GeofenceTransitionCallback,
+ GeofenceMonitorStatusCallback,
+ GeofenceAddCallback,
+ GeofenceRemoveCallback,
+ GeofencePauseCallback,
+ GeofenceResumeCallback,
+ SetThreadEvent
+};
+
+/*
+ * Initializes the Fused Location Provider in the native side. It ensures that
+ * the Flp interfaces are initialized properly.
+ */
+static void Init(JNIEnv* env, jobject obj) {
+ if(sHardwareDevice != NULL) {
+ ALOGD("Hardware Device already opened.");
+ return;
+ }
+
+ const hw_module_t* module = NULL;
+ int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, &module);
+ if(err != 0) {
+ ALOGE("Error hw_get_module '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
+ return;
+ }
+
+ err = module->methods->open(
+ module,
+ FUSED_LOCATION_HARDWARE_MODULE_ID, &sHardwareDevice);
+ if(err != 0) {
+ ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
+ return;
+ }
+
+ sFlpInterface = NULL;
+ flp_device_t* flp_device = reinterpret_cast<flp_device_t*>(sHardwareDevice);
+ sFlpInterface = flp_device->get_flp_interface(flp_device);
+
+ if(sFlpInterface != NULL) {
+ sFlpDiagnosticInterface = reinterpret_cast<const FlpDiagnosticInterface*>(
+ sFlpInterface->get_extension(FLP_DIAGNOSTIC_INTERFACE)
+ );
+
+ sFlpGeofencingInterface = reinterpret_cast<const FlpGeofencingInterface*>(
+ sFlpInterface->get_extension(FLP_GEOFENCING_INTERFACE)
+ );
+
+ sFlpDeviceContextInterface = reinterpret_cast<const FlpDeviceContextInterface*>(
+ sFlpInterface->get_extension(FLP_DEVICE_CONTEXT_INTERFACE)
+ );
+ }
+
+ if(sCallbacksObj == NULL) {
+ sCallbacksObj = env->NewGlobalRef(obj);
+ }
+
+ // initialize the Flp interfaces
+ if(sFlpInterface == NULL || sFlpInterface->init(&sFlpCallbacks) != 0) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ if(sFlpDiagnosticInterface != NULL) {
+ sFlpDiagnosticInterface->init(&sFlpDiagnosticCallbacks);
+ }
+
+ if(sFlpGeofencingInterface != NULL) {
+ sFlpGeofencingInterface->init(&sFlpGeofenceCallbacks);
+ }
+
+ // TODO: inject any device context if when needed
+}
+
+static jboolean IsSupported(JNIEnv* env, jclass clazz) {
+ return sFlpInterface != NULL;
+}
+
+static jint GetBatchSize(JNIEnv* env, jobject object) {
+ if(sFlpInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ return sFlpInterface->get_batch_size();
+}
+
+static void StartBatching(
+ JNIEnv* env,
+ jobject object,
+ jint id,
+ jobject optionsObject) {
+ if(sFlpInterface == NULL || optionsObject == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ FlpBatchOptions options;
+ TranslateFromObject(env, optionsObject, options);
+ int result = sFlpInterface->start_batching(id, &options);
+ ThrowOnError(env, result, __FUNCTION__);
+}
+
+static void UpdateBatchingOptions(
+ JNIEnv* env,
+ jobject object,
+ jint id,
+ jobject optionsObject) {
+ if(sFlpInterface == NULL || optionsObject == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ FlpBatchOptions options;
+ TranslateFromObject(env, optionsObject, options);
+ int result = sFlpInterface->update_batching_options(id, &options);
+ ThrowOnError(env, result, __FUNCTION__);
+}
+
+static void StopBatching(JNIEnv* env, jobject object, jint id) {
+ if(sFlpInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ sFlpInterface->stop_batching(id);
+}
+
+static void Cleanup(JNIEnv* env, jobject object) {
+ if(sFlpInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ sFlpInterface->cleanup();
+
+ if(sCallbacksObj != NULL) {
+ env->DeleteGlobalRef(sCallbacksObj);
+ sCallbacksObj = NULL;
+ }
+
+ sFlpInterface = NULL;
+ sFlpDiagnosticInterface = NULL;
+ sFlpDeviceContextInterface = NULL;
+ sFlpGeofencingInterface = NULL;
+
+ if(sHardwareDevice != NULL) {
+ sHardwareDevice->close(sHardwareDevice);
+ sHardwareDevice = NULL;
+ }
+}
+
+static void GetBatchedLocation(JNIEnv* env, jobject object, jint lastNLocations) {
+ if(sFlpInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ sFlpInterface->get_batched_location(lastNLocations);
+}
+
+static void InjectLocation(JNIEnv* env, jobject object, jobject locationObject) {
+ if(locationObject == NULL) {
+ ALOGE("Invalid location for injection: %p", locationObject);
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ if(sFlpInterface == NULL) {
+ // there is no listener, bail
+ return;
+ }
+
+ FlpLocation location;
+ TranslateFromObject(env, locationObject, location);
+ int result = sFlpInterface->inject_location(&location);
+ if (result != FLP_RESULT_ERROR) {
+ // do not throw but log, this operation should be fire and forget
+ ALOGE("Error %d in '%s'", result, __FUNCTION__);
+ }
+}
+
+static jboolean IsDiagnosticSupported() {
+ return sFlpDiagnosticInterface != NULL;
+}
+
+static void InjectDiagnosticData(JNIEnv* env, jobject object, jstring stringData) {
+ if(stringData == NULL) {
+ ALOGE("Invalid diagnostic data for injection: %p", stringData);
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ if(sFlpDiagnosticInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ int length = env->GetStringLength(stringData);
+ const jchar* data = env->GetStringChars(stringData, /* isCopy */ NULL);
+ if(data == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ int result = sFlpDiagnosticInterface->inject_data((char*) data, length);
+ ThrowOnError(env, result, __FUNCTION__);
+}
+
+static jboolean IsDeviceContextSupported() {
+ return sFlpDeviceContextInterface != NULL;
+}
+
+static void InjectDeviceContext(JNIEnv* env, jobject object, jint enabledMask) {
+ if(sFlpDeviceContextInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ int result = sFlpDeviceContextInterface->inject_device_context(enabledMask);
+ ThrowOnError(env, result, __FUNCTION__);
+}
+
+static jboolean IsGeofencingSupported() {
+ return sFlpGeofencingInterface != NULL;
+}
+
+static void AddGeofences(
+ JNIEnv* env,
+ jobject object,
+ jintArray geofenceIdsArray,
+ jobjectArray geofencesArray) {
+ if(geofencesArray == NULL) {
+ ALOGE("Invalid Geofences to add: %p", geofencesArray);
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ if (sFlpGeofencingInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ jint geofencesCount = env->GetArrayLength(geofenceIdsArray);
+ Geofence* geofences = new Geofence[geofencesCount];
+ if (geofences == NULL) {
+ ThrowOnError(env, FLP_RESULT_INSUFFICIENT_MEMORY, __FUNCTION__);
+ }
+
+ jint* ids = env->GetIntArrayElements(geofenceIdsArray, /* isCopy */ NULL);
+ for (int i = 0; i < geofencesCount; ++i) {
+ geofences[i].geofence_id = ids[i];
+
+ // TODO: fill in the GeofenceData
+
+ // TODO: fill in the GeofenceOptions
+ }
+
+ sFlpGeofencingInterface->add_geofences(geofencesCount, &geofences);
+ if (geofences != NULL) delete[] geofences;
+}
+
+static void PauseGeofence(JNIEnv* env, jobject object, jint geofenceId) {
+ if(sFlpGeofencingInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ sFlpGeofencingInterface->pause_geofence(geofenceId);
+}
+
+static void ResumeGeofence(
+ JNIEnv* env,
+ jobject object,
+ jint geofenceId,
+ jint monitorTransitions) {
+ if(sFlpGeofencingInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ sFlpGeofencingInterface->resume_geofence(geofenceId, monitorTransitions);
+}
+
+static void ModifyGeofenceOption(
+ JNIEnv* env,
+ jobject object,
+ jint geofenceId,
+ jint lastTransition,
+ jint monitorTransitions,
+ jint notificationResponsiveness,
+ jint unknownTimer,
+ jint sourcesToUse) {
+ if(sFlpGeofencingInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ GeofenceOptions options = {
+ lastTransition,
+ monitorTransitions,
+ notificationResponsiveness,
+ unknownTimer,
+ (uint32_t)sourcesToUse
+ };
+
+ sFlpGeofencingInterface->modify_geofence_option(geofenceId, &options);
+}
+
+static void RemoveGeofences(
+ JNIEnv* env,
+ jobject object,
+ jintArray geofenceIdsArray) {
+ if(sFlpGeofencingInterface == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ jsize geofenceIdsCount = env->GetArrayLength(geofenceIdsArray);
+ jint* geofenceIds = env->GetIntArrayElements(geofenceIdsArray, /* isCopy */ NULL);
+ if(geofenceIds == NULL) {
+ ThrowOnError(env, FLP_RESULT_ERROR, __FUNCTION__);
+ }
+
+ sFlpGeofencingInterface->remove_geofences(geofenceIdsCount, geofenceIds);
+}
+
+static JNINativeMethod sMethods[] = {
+ //{"name", "signature", functionPointer }
+ {"nativeClassInit", "()V", reinterpret_cast<void*>(ClassInit)},
+ {"nativeInit", "()V", reinterpret_cast<void*>(Init)},
+ {"nativeCleanup", "()V", reinterpret_cast<void*>(Cleanup)},
+ {"nativeIsSupported", "()Z", reinterpret_cast<void*>(IsSupported)},
+ {"nativeGetBatchSize", "()I", reinterpret_cast<void*>(GetBatchSize)},
+ {"nativeStartBatching",
+ "(ILandroid/location/FusedBatchOptions;)V",
+ reinterpret_cast<void*>(StartBatching)},
+ {"nativeUpdateBatchingOptions",
+ "(ILandroid/location/FusedBatchOptions;)V",
+ reinterpret_cast<void*>(UpdateBatchingOptions)},
+ {"nativeStopBatching", "(I)V", reinterpret_cast<void*>(StopBatching)},
+ {"nativeRequestBatchedLocation",
+ "(I)V",
+ reinterpret_cast<void*>(GetBatchedLocation)},
+ {"nativeInjectLocation",
+ "(Landroid/location/Location;)V",
+ reinterpret_cast<void*>(InjectLocation)},
+ {"nativeIsDiagnosticSupported",
+ "()Z",
+ reinterpret_cast<void*>(IsDiagnosticSupported)},
+ {"nativeInjectDiagnosticData",
+ "(Ljava/lang/String;)V",
+ reinterpret_cast<void*>(InjectDiagnosticData)},
+ {"nativeIsDeviceContextSupported",
+ "()Z",
+ reinterpret_cast<void*>(IsDeviceContextSupported)},
+ {"nativeInjectDeviceContext",
+ "(I)V",
+ reinterpret_cast<void*>(InjectDeviceContext)},
+ {"nativeIsGeofencingSupported",
+ "()Z",
+ reinterpret_cast<void*>(IsGeofencingSupported)},
+ {"nativeAddGeofences",
+ "([I[Landroid/location/Geofence;)V",
+ reinterpret_cast<void*>(AddGeofences)},
+ {"nativePauseGeofence", "(I)V", reinterpret_cast<void*>(PauseGeofence)},
+ {"nativeResumeGeofence", "(II)V", reinterpret_cast<void*>(ResumeGeofence)},
+ {"nativeModifyGeofenceOption",
+ "(IIIIII)V",
+ reinterpret_cast<void*>(ModifyGeofenceOption)},
+ {"nativeRemoveGeofences", "([I)V", reinterpret_cast<void*>(RemoveGeofences)}
+};
+
+/*
+ * Registration method invoked on JNI Load.
+ */
+int register_android_server_location_FlpHardwareProvider(JNIEnv* env) {
+ return jniRegisterNativeMethods(
+ env,
+ "com/android/server/location/FlpHardwareProvider",
+ sMethods,
+ NELEM(sMethods)
+ );
+}
+
+} /* name-space Android */
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 736ef24..5427277 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -32,6 +32,7 @@ int register_android_server_UsbHostManager(JNIEnv* env);
int register_android_server_VibratorService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
int register_android_server_location_GpsLocationProvider(JNIEnv* env);
+int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
int register_android_server_AssetAtlasService(JNIEnv* env);
};
@@ -61,6 +62,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
register_android_server_VibratorService(env);
register_android_server_SystemServer(env);
register_android_server_location_GpsLocationProvider(env);
+ register_android_server_location_FlpHardwareProvider(env);
register_android_server_connectivity_Vpn(env);
register_android_server_AssetAtlasService(env);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
index 4171bb5..361f5d7 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java
@@ -1148,14 +1148,6 @@ public final class Canvas_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_drawPicture(int nativeCanvas,
- int nativePicture) {
- // FIXME
- Bridge.getLog().fidelityWarning(LayoutLog.TAG_UNSUPPORTED,
- "Canvas.drawPicture is not supported.", null, null /*data*/);
- }
-
- @LayoutlibDelegate
/*package*/ static void finalizer(int nativeCanvas) {
// get the delegate from the native int so that it can be disposed.
Canvas_Delegate canvasDelegate = sManager.getDelegate(nativeCanvas);
diff --git a/wifi/java/android/net/wifi/WifiMonitor.java b/wifi/java/android/net/wifi/WifiMonitor.java
index fe3c709..92b8e46 100644
--- a/wifi/java/android/net/wifi/WifiMonitor.java
+++ b/wifi/java/android/net/wifi/WifiMonitor.java
@@ -32,7 +32,10 @@ import android.util.Log;
import com.android.internal.util.Protocol;
import com.android.internal.util.StateMachine;
+import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
@@ -44,6 +47,7 @@ import java.util.regex.Matcher;
*/
public class WifiMonitor {
+ private static final boolean DBG = false;
private static final String TAG = "WifiMonitor";
/** Events we receive from the supplicant daemon */
@@ -279,9 +283,6 @@ public class WifiMonitor {
/* AP-STA-DISCONNECTED 42:fc:89:a8:96:09 */
private static final String AP_STA_DISCONNECTED_STR = "AP-STA-DISCONNECTED";
- private final StateMachine mStateMachine;
- private final WifiNative mWifiNative;
-
/* Supplicant events reported to a state machine */
private static final int BASE = Protocol.BASE_WIFI_MONITOR;
@@ -347,164 +348,324 @@ public class WifiMonitor {
private static final String WPA_RECV_ERROR_STR = "recv error";
/**
- * Tracks consecutive receive errors
- */
- private int mRecvErrors = 0;
-
- /**
* Max errors before we close supplicant connection
*/
private static final int MAX_RECV_ERRORS = 10;
+ private final String mInterfaceName;
+ private final WifiNative mWifiNative;
+ private final StateMachine mWifiStateMachine;
+ private boolean mMonitoring;
+
public WifiMonitor(StateMachine wifiStateMachine, WifiNative wifiNative) {
- mStateMachine = wifiStateMachine;
+ if (DBG) Log.d(TAG, "Creating WifiMonitor");
mWifiNative = wifiNative;
+ mInterfaceName = wifiNative.mInterfaceName;
+ mWifiStateMachine = wifiStateMachine;
+ mMonitoring = false;
+
+ WifiMonitorSingleton.getMonitor().registerInterfaceMonitor(mInterfaceName, this);
}
public void startMonitoring() {
- new MonitorThread().start();
+ WifiMonitorSingleton.getMonitor().startMonitoring(mInterfaceName);
}
- class MonitorThread extends Thread {
- public MonitorThread() {
- super("WifiMonitor");
+ public void stopMonitoring() {
+ WifiMonitorSingleton.getMonitor().stopMonitoring(mInterfaceName);
+ }
+
+ public void stopSupplicant() {
+ WifiMonitorSingleton.getMonitor().stopSupplicant();
+ }
+
+ public void killSupplicant(boolean p2pSupported) {
+ WifiMonitorSingleton.getMonitor().killSupplicant(p2pSupported);
+ }
+
+ private static class WifiMonitorSingleton {
+ private static Object sSingletonLock = new Object();
+ private static WifiMonitorSingleton sWifiMonitorSingleton = null;
+ private HashMap<String, WifiMonitor> mIfaceMap = new HashMap<String, WifiMonitor>();
+ private boolean mConnected = false;
+ private WifiNative mWifiNative;
+
+ private WifiMonitorSingleton() {
}
- public void run() {
+ static WifiMonitorSingleton getMonitor() {
+ if (DBG) Log.d(TAG, "WifiMonitorSingleton gotten");
+ synchronized (sSingletonLock) {
+ if (sWifiMonitorSingleton == null) {
+ if (DBG) Log.d(TAG, "WifiMonitorSingleton created");
+ sWifiMonitorSingleton = new WifiMonitorSingleton();
+ }
+ }
+ return sWifiMonitorSingleton;
+ }
- if (connectToSupplicant()) {
- // Send a message indicating that it is now possible to send commands
- // to the supplicant
- mStateMachine.sendMessage(SUP_CONNECTION_EVENT);
- } else {
- mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
+ public synchronized void startMonitoring(String iface) {
+ WifiMonitor m = mIfaceMap.get(iface);
+ if (m == null) {
+ Log.e(TAG, "startMonitor called with unknown iface=" + iface);
return;
}
+ Log.d(TAG, "startMonitoring(" + iface + ") with mConnected = " + mConnected);
+
+ if (mConnected) {
+ m.mMonitoring = true;
+ m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
+ } else {
+ if (DBG) Log.d(TAG, "connecting to supplicant");
+ int connectTries = 0;
+ while (true) {
+ if (mWifiNative.connectToSupplicant()) {
+ m.mMonitoring = true;
+ m.mWifiStateMachine.sendMessage(SUP_CONNECTION_EVENT);
+ new MonitorThread(mWifiNative, this).start();
+ mConnected = true;
+ break;
+ }
+ if (connectTries++ < 5) {
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ignore) {
+ }
+ } else {
+ mIfaceMap.remove(iface);
+ m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
+ break;
+ }
+ }
+ }
+ }
+
+ public synchronized void stopMonitoring(String iface) {
+ WifiMonitor m = mIfaceMap.get(iface);
+ if (DBG) Log.d(TAG, "stopMonitoring(" + iface + ") = " + m.mWifiStateMachine);
+ m.mMonitoring = false;
+ m.mWifiStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
+ }
+
+ public synchronized void registerInterfaceMonitor(String iface, WifiMonitor m) {
+ if (DBG) Log.d(TAG, "registerInterface(" + iface + "+" + m.mWifiStateMachine + ")");
+ mIfaceMap.put(iface, m);
+ if (mWifiNative == null) {
+ mWifiNative = m.mWifiNative;
+ }
+ }
+
+ public synchronized void unregisterInterfaceMonitor(String iface) {
+ // REVIEW: When should we call this? If this isn't called, then WifiMonitor
+ // objects will remain in the mIfaceMap; and won't ever get deleted
+
+ WifiMonitor m = mIfaceMap.remove(iface);
+ if (DBG) Log.d(TAG, "unregisterInterface(" + iface + "+" + m.mWifiStateMachine + ")");
+ }
+
+ public synchronized void stopSupplicant() {
+ mWifiNative.stopSupplicant();
+ }
+
+ public synchronized void killSupplicant(boolean p2pSupported) {
+ mWifiNative.killSupplicant(p2pSupported);
+ mConnected = false;
+ Iterator<Map.Entry<String, WifiMonitor>> it = mIfaceMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, WifiMonitor> e = it.next();
+ WifiMonitor m = e.getValue();
+ m.mMonitoring = false;
+ }
+ }
+
+ private synchronized WifiMonitor getMonitor(String iface) {
+ return mIfaceMap.get(iface);
+ }
+ }
+
+ private static class MonitorThread extends Thread {
+ private final WifiNative mWifiNative;
+ private final WifiMonitorSingleton mWifiMonitorSingleton;
+ private int mRecvErrors = 0;
+ private StateMachine mStateMachine = null;
+
+ public MonitorThread(WifiNative wifiNative, WifiMonitorSingleton wifiMonitorSingleton) {
+ super("WifiMonitor");
+ mWifiNative = wifiNative;
+ mWifiMonitorSingleton = wifiMonitorSingleton;
+ }
+
+ public void run() {
//noinspection InfiniteLoopStatement
for (;;) {
String eventStr = mWifiNative.waitForEvent();
// Skip logging the common but mostly uninteresting scan-results event
- if (false && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
+ if (DBG && eventStr.indexOf(SCAN_RESULTS_STR) == -1) {
Log.d(TAG, "Event [" + eventStr + "]");
}
- if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
- if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
- 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) {
- mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
- } else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
- mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
- } else if (eventStr.startsWith(WPS_FAIL_STR)) {
- handleWpsFailEvent(eventStr);
- } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
- mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
- } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
- mStateMachine.sendMessage(WPS_TIMEOUT_EVENT);
- } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {
- handleP2pEvents(eventStr);
- } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {
- handleHostApEvents(eventStr);
+
+ WifiMonitor m = null;
+ mStateMachine = null;
+
+ if (eventStr.startsWith("IFNAME=")) {
+ int space = eventStr.indexOf(' ');
+ if (space != -1) {
+ String iface = eventStr.substring(7,space);
+ m = mWifiMonitorSingleton.getMonitor(iface);
+ if (m != null) {
+ if (m.mMonitoring) {
+ mStateMachine = m.mWifiStateMachine;
+ eventStr = eventStr.substring(space + 1);
+ }
+ else {
+ if (DBG) Log.d(TAG, "Dropping event because monitor (" + iface +
+ ") is stopped");
+ continue;
+ }
+ }
+ else {
+ eventStr = eventStr.substring(space + 1);
+ }
}
- continue;
}
- String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
- int nameEnd = eventName.indexOf(' ');
- if (nameEnd != -1)
- eventName = eventName.substring(0, nameEnd);
- if (eventName.length() == 0) {
- if (false) Log.i(TAG, "Received wpa_supplicant event with empty event name");
- continue;
- }
- /*
- * Map event name into event enum
- */
- int event;
- if (eventName.equals(CONNECTED_STR))
- event = CONNECTED;
- else if (eventName.equals(DISCONNECTED_STR))
- event = DISCONNECTED;
- else if (eventName.equals(STATE_CHANGE_STR))
- event = STATE_CHANGE;
- else if (eventName.equals(SCAN_RESULTS_STR))
- event = SCAN_RESULTS;
- else if (eventName.equals(LINK_SPEED_STR))
- event = LINK_SPEED;
- else if (eventName.equals(TERMINATING_STR))
- event = TERMINATING;
- else if (eventName.equals(DRIVER_STATE_STR))
- event = DRIVER_STATE;
- else if (eventName.equals(EAP_FAILURE_STR))
- event = EAP_FAILURE;
- else if (eventName.equals(ASSOC_REJECT_STR))
- event = ASSOC_REJECT;
- else
- event = UNKNOWN;
-
- String eventData = eventStr;
- if (event == DRIVER_STATE || event == LINK_SPEED)
- eventData = eventData.split(" ")[1];
- else if (event == STATE_CHANGE || event == EAP_FAILURE) {
- int ind = eventStr.indexOf(" ");
- if (ind != -1) {
- eventData = eventStr.substring(ind + 1);
+ if (mStateMachine != null) {
+ if (dispatchEvent(eventStr)) {
+ break;
}
} else {
- int ind = eventStr.indexOf(" - ");
- if (ind != -1) {
- eventData = eventStr.substring(ind + 3);
- }
- }
-
- if (event == STATE_CHANGE) {
- handleSupplicantStateChange(eventData);
- } else if (event == DRIVER_STATE) {
- handleDriverEvent(eventData);
- } else if (event == TERMINATING) {
- /**
- * Close the supplicant connection if we see
- * too many recv errors
- */
- if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
- if (++mRecvErrors > MAX_RECV_ERRORS) {
- if (false) {
- Log.d(TAG, "too many recv errors, closing connection");
- }
- } else {
- continue;
+ if (DBG) Log.d(TAG, "Sending to all monitors because there's no interface id");
+ boolean done = false;
+ Iterator<Map.Entry<String, WifiMonitor>> it =
+ mWifiMonitorSingleton.mIfaceMap.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, WifiMonitor> e = it.next();
+ m = e.getValue();
+ mStateMachine = m.mWifiStateMachine;
+ if (dispatchEvent(eventStr)) {
+ done = true;
}
}
- // notify and exit
- mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
- break;
- } else if (event == EAP_FAILURE) {
- if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
- mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
+ if (done) {
+ // After this thread terminates, we'll no longer
+ // be connected to the supplicant
+ if (DBG) Log.d(TAG, "Disconnecting from the supplicant, no more events");
+ mWifiMonitorSingleton.mConnected = false;
+ break;
}
- } else if (event == ASSOC_REJECT) {
- mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT);
- } else {
- handleEvent(event, eventData);
}
- mRecvErrors = 0;
}
}
- private boolean connectToSupplicant() {
- int connectTries = 0;
+ /* @return true if the event was supplicant disconnection */
+ private boolean dispatchEvent(String eventStr) {
+
+ if (!eventStr.startsWith(EVENT_PREFIX_STR)) {
+ if (eventStr.startsWith(WPA_EVENT_PREFIX_STR) &&
+ 0 < eventStr.indexOf(PASSWORD_MAY_BE_INCORRECT_STR)) {
+ mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
+ } else if (eventStr.startsWith(WPS_SUCCESS_STR)) {
+ mStateMachine.sendMessage(WPS_SUCCESS_EVENT);
+ } else if (eventStr.startsWith(WPS_FAIL_STR)) {
+ handleWpsFailEvent(eventStr);
+ } else if (eventStr.startsWith(WPS_OVERLAP_STR)) {
+ mStateMachine.sendMessage(WPS_OVERLAP_EVENT);
+ } else if (eventStr.startsWith(WPS_TIMEOUT_STR)) {
+ mStateMachine.sendMessage(WPS_TIMEOUT_EVENT);
+ } else if (eventStr.startsWith(P2P_EVENT_PREFIX_STR)) {
+ handleP2pEvents(eventStr);
+ } else if (eventStr.startsWith(HOST_AP_EVENT_PREFIX_STR)) {
+ handleHostApEvents(eventStr);
+ }
+ else {
+ if (DBG) Log.w(TAG, "couldn't identify event type - " + eventStr);
+ }
+ return false;
+ }
- while (true) {
- if (mWifiNative.connectToSupplicant()) {
- return true;
+ String eventName = eventStr.substring(EVENT_PREFIX_LEN_STR);
+ int nameEnd = eventName.indexOf(' ');
+ if (nameEnd != -1)
+ eventName = eventName.substring(0, nameEnd);
+ if (eventName.length() == 0) {
+ if (DBG) Log.i(TAG, "Received wpa_supplicant event with empty event name");
+ return false;
+ }
+ /*
+ * Map event name into event enum
+ */
+ int event;
+ if (eventName.equals(CONNECTED_STR))
+ event = CONNECTED;
+ else if (eventName.equals(DISCONNECTED_STR))
+ event = DISCONNECTED;
+ else if (eventName.equals(STATE_CHANGE_STR))
+ event = STATE_CHANGE;
+ else if (eventName.equals(SCAN_RESULTS_STR))
+ event = SCAN_RESULTS;
+ else if (eventName.equals(LINK_SPEED_STR))
+ event = LINK_SPEED;
+ else if (eventName.equals(TERMINATING_STR))
+ event = TERMINATING;
+ else if (eventName.equals(DRIVER_STATE_STR))
+ event = DRIVER_STATE;
+ else if (eventName.equals(EAP_FAILURE_STR))
+ event = EAP_FAILURE;
+ else if (eventName.equals(ASSOC_REJECT_STR))
+ event = ASSOC_REJECT;
+ else
+ event = UNKNOWN;
+
+ String eventData = eventStr;
+ if (event == DRIVER_STATE || event == LINK_SPEED)
+ eventData = eventData.split(" ")[1];
+ else if (event == STATE_CHANGE || event == EAP_FAILURE) {
+ int ind = eventStr.indexOf(" ");
+ if (ind != -1) {
+ eventData = eventStr.substring(ind + 1);
}
- if (connectTries++ < 5) {
- nap(1);
- } else {
- break;
+ } else {
+ int ind = eventStr.indexOf(" - ");
+ if (ind != -1) {
+ eventData = eventStr.substring(ind + 3);
+ }
+ }
+
+ if (event == STATE_CHANGE) {
+ handleSupplicantStateChange(eventData);
+ } else if (event == DRIVER_STATE) {
+ handleDriverEvent(eventData);
+ } else if (event == TERMINATING) {
+ /**
+ * Close the supplicant connection if we see
+ * too many recv errors
+ */
+ if (eventData.startsWith(WPA_RECV_ERROR_STR)) {
+ if (++mRecvErrors > MAX_RECV_ERRORS) {
+ if (DBG) {
+ Log.d(TAG, "too many recv errors, closing connection");
+ }
+ } else {
+ return false;
+ }
+ }
+
+ // notify and exit
+ mStateMachine.sendMessage(SUP_DISCONNECTION_EVENT);
+ return true;
+ } else if (event == EAP_FAILURE) {
+ if (eventData.startsWith(EAP_AUTH_FAILURE_STR)) {
+ mStateMachine.sendMessage(AUTHENTICATION_FAILURE_EVENT);
}
+ } else if (event == ASSOC_REJECT) {
+ mStateMachine.sendMessage(ASSOCIATION_REJECTION_EVENT);
+ } else {
+ handleEvent(event, eventData);
}
+ mRecvErrors = 0;
return false;
}
@@ -723,71 +884,60 @@ public class WifiMonitor {
}
notifySupplicantStateChange(networkId, wifiSsid, BSSID, newSupplicantState);
}
- }
- private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) {
- String BSSID = null;
- int networkId = -1;
- if (newState == NetworkInfo.DetailedState.CONNECTED) {
- Matcher match = mConnectedEventPattern.matcher(data);
- if (!match.find()) {
- if (false) Log.d(TAG, "Could not find BSSID in CONNECTED event string");
- } else {
- BSSID = match.group(1);
- try {
- networkId = Integer.parseInt(match.group(2));
- } catch (NumberFormatException e) {
- networkId = -1;
+ private void handleNetworkStateChange(NetworkInfo.DetailedState newState, String data) {
+ String BSSID = null;
+ int networkId = -1;
+ if (newState == NetworkInfo.DetailedState.CONNECTED) {
+ Matcher match = mConnectedEventPattern.matcher(data);
+ if (!match.find()) {
+ if (DBG) Log.d(TAG, "Could not find BSSID in CONNECTED event string");
+ } else {
+ BSSID = match.group(1);
+ try {
+ networkId = Integer.parseInt(match.group(2));
+ } catch (NumberFormatException e) {
+ networkId = -1;
+ }
}
+ notifyNetworkStateChange(newState, BSSID, networkId);
}
}
- notifyNetworkStateChange(newState, BSSID, networkId);
- }
- /**
- * Send the state machine a notification that the state of Wifi connectivity
- * has changed.
- * @param networkId the configured network on which the state change occurred
- * @param newState the new network state
- * @param BSSID when the new state is {@link DetailedState#CONNECTED
- * NetworkInfo.DetailedState.CONNECTED},
- * this is the MAC address of the access point. Otherwise, it
- * is {@code null}.
- */
- void notifyNetworkStateChange(NetworkInfo.DetailedState newState, String BSSID, int netId) {
- if (newState == NetworkInfo.DetailedState.CONNECTED) {
- Message m = mStateMachine.obtainMessage(NETWORK_CONNECTION_EVENT,
- netId, 0, BSSID);
- mStateMachine.sendMessage(m);
- } else {
- Message m = mStateMachine.obtainMessage(NETWORK_DISCONNECTION_EVENT,
- netId, 0, BSSID);
- mStateMachine.sendMessage(m);
+ /**
+ * Send the state machine a notification that the state of Wifi connectivity
+ * has changed.
+ * @param networkId the configured network on which the state change occurred
+ * @param newState the new network state
+ * @param BSSID when the new state is {@link DetailedState#CONNECTED
+ * NetworkInfo.DetailedState.CONNECTED},
+ * this is the MAC address of the access point. Otherwise, it
+ * is {@code null}.
+ */
+ void notifyNetworkStateChange(NetworkInfo.DetailedState newState, String BSSID, int netId) {
+ if (newState == NetworkInfo.DetailedState.CONNECTED) {
+ Message m = mStateMachine.obtainMessage(NETWORK_CONNECTION_EVENT,
+ netId, 0, BSSID);
+ mStateMachine.sendMessage(m);
+ } else {
+ Message m = mStateMachine.obtainMessage(NETWORK_DISCONNECTION_EVENT,
+ netId, 0, BSSID);
+ mStateMachine.sendMessage(m);
+ }
}
- }
- /**
- * Send the state machine a notification that the state of the supplicant
- * has changed.
- * @param networkId the configured network on which the state change occurred
- * @param wifiSsid network name
- * @param BSSID network address
- * @param newState the new {@code SupplicantState}
- */
- void notifySupplicantStateChange(int networkId, WifiSsid wifiSsid, String BSSID,
- SupplicantState newState) {
- mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
- new StateChangeResult(networkId, wifiSsid, BSSID, newState)));
- }
-
- /**
- * Sleep for a period of time.
- * @param secs the number of seconds to sleep
- */
- private static void nap(int secs) {
- try {
- Thread.sleep(secs * 1000);
- } catch (InterruptedException ignore) {
+ /**
+ * Send the state machine a notification that the state of the supplicant
+ * has changed.
+ * @param networkId the configured network on which the state change occurred
+ * @param wifiSsid network name
+ * @param BSSID network address
+ * @param newState the new {@code SupplicantState}
+ */
+ void notifySupplicantStateChange(int networkId, WifiSsid wifiSsid, String BSSID,
+ SupplicantState newState) {
+ mStateMachine.sendMessage(mStateMachine.obtainMessage(SUPPLICANT_STATE_CHANGE_EVENT,
+ new StateChangeResult(networkId, wifiSsid, BSSID, newState)));
}
}
}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index b1dd2ce..d30c7cf 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -47,7 +47,9 @@ public class WifiNative {
static final int SCAN_WITHOUT_CONNECTION_SETUP = 1;
static final int SCAN_WITH_CONNECTION_SETUP = 2;
- String mInterface = "";
+ public final String mInterfaceName;
+ public final String mInterfacePrefix;
+
private boolean mSuspendOptEnabled = false;
public native static boolean loadDriver();
@@ -62,52 +64,53 @@ public class WifiNative {
or when the supplicant is hung */
public native static boolean killSupplicant(boolean p2pSupported);
- private native boolean connectToSupplicant(String iface);
+ private native boolean connectToSupplicantNative();
- private native void closeSupplicantConnection(String iface);
+ private native void closeSupplicantConnectionNative();
/**
* Wait for the supplicant to send an event, returning the event string.
* @return the event string sent by the supplicant.
*/
- private native String waitForEvent(String iface);
+ private native String waitForEventNative();
- private native boolean doBooleanCommand(String iface, String command);
+ private native boolean doBooleanCommandNative(String command);
- private native int doIntCommand(String iface, String command);
+ private native int doIntCommandNative(String command);
- private native String doStringCommand(String iface, String command);
+ private native String doStringCommandNative(String command);
- public WifiNative(String iface) {
- mInterface = iface;
- mTAG = "WifiNative-" + iface;
+ public WifiNative(String interfaceName) {
+ mInterfaceName = interfaceName;
+ mInterfacePrefix = "IFNAME=" + interfaceName + " ";
+ mTAG = "WifiNative-" + interfaceName;
}
public boolean connectToSupplicant() {
- return connectToSupplicant(mInterface);
+ return connectToSupplicantNative();
}
public void closeSupplicantConnection() {
- closeSupplicantConnection(mInterface);
+ closeSupplicantConnectionNative();
}
public String waitForEvent() {
- return waitForEvent(mInterface);
+ return waitForEventNative();
}
private boolean doBooleanCommand(String command) {
if (DBG) Log.d(mTAG, "doBoolean: " + command);
- return doBooleanCommand(mInterface, command);
+ return doBooleanCommandNative(mInterfacePrefix + command);
}
private int doIntCommand(String command) {
if (DBG) Log.d(mTAG, "doInt: " + command);
- return doIntCommand(mInterface, command);
+ return doIntCommandNative(mInterfacePrefix + command);
}
private String doStringCommand(String command) {
if (DBG) Log.d(mTAG, "doString: " + command);
- return doStringCommand(mInterface, command);
+ return doStringCommandNative(mInterfacePrefix + command);
}
public boolean ping() {
@@ -411,9 +414,9 @@ public class WifiNative {
public boolean startWpsPbc(String iface, String bssid) {
if (TextUtils.isEmpty(bssid)) {
- return doBooleanCommand("IFNAME=" + iface + " WPS_PBC");
+ return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC");
} else {
- return doBooleanCommand("IFNAME=" + iface + " WPS_PBC " + bssid);
+ return doBooleanCommandNative("IFNAME=" + iface + " WPS_PBC " + bssid);
}
}
@@ -424,7 +427,7 @@ public class WifiNative {
public boolean startWpsPinKeypad(String iface, String pin) {
if (TextUtils.isEmpty(pin)) return false;
- return doBooleanCommand("IFNAME=" + iface + " WPS_PIN any " + pin);
+ return doBooleanCommandNative("IFNAME=" + iface + " WPS_PIN any " + pin);
}
@@ -438,9 +441,9 @@ public class WifiNative {
public String startWpsPinDisplay(String iface, String bssid) {
if (TextUtils.isEmpty(bssid)) {
- return doStringCommand("IFNAME=" + iface + " WPS_PIN any");
+ return doStringCommandNative("IFNAME=" + iface + " WPS_PIN any");
} else {
- return doStringCommand("IFNAME=" + iface + " WPS_PIN " + bssid);
+ return doStringCommandNative("IFNAME=" + iface + " WPS_PIN " + bssid);
}
}
@@ -492,7 +495,7 @@ public class WifiNative {
}
public boolean setP2pGroupIdle(String iface, int time) {
- return doBooleanCommand("IFNAME=" + iface + " SET p2p_group_idle " + time);
+ return doBooleanCommandNative("IFNAME=" + iface + " SET p2p_group_idle " + time);
}
public void setPowerSave(boolean enabled) {
@@ -505,9 +508,9 @@ public class WifiNative {
public boolean setP2pPowerSave(String iface, boolean enabled) {
if (enabled) {
- return doBooleanCommand("IFNAME=" + iface + " P2P_SET ps 1");
+ return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 1");
} else {
- return doBooleanCommand("IFNAME=" + iface + " P2P_SET ps 0");
+ return doBooleanCommandNative("IFNAME=" + iface + " P2P_SET ps 0");
}
}
@@ -645,7 +648,7 @@ public class WifiNative {
public boolean p2pGroupRemove(String iface) {
if (TextUtils.isEmpty(iface)) return false;
- return doBooleanCommand("P2P_GROUP_REMOVE " + iface);
+ return doBooleanCommandNative("IFNAME=" + iface + " P2P_GROUP_REMOVE " + iface);
}
public boolean p2pReject(String deviceAddress) {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 4628c91..1fcd609 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -68,6 +68,7 @@ import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.WorkSource;
import android.provider.Settings;
+import android.util.Log;
import android.util.LruCache;
import android.text.TextUtils;
@@ -543,7 +544,6 @@ public class WifiStateMachine extends StateMachine {
public WifiStateMachine(Context context, String wlanInterface) {
super("WifiStateMachine");
-
mContext = context;
mInterfaceName = wlanInterface;
@@ -888,6 +888,7 @@ public class WifiStateMachine extends StateMachine {
* TODO: doc
*/
public void setOperationalMode(int mode) {
+ if (DBG) log("setting operational mode to " + String.valueOf(mode));
sendMessage(CMD_SET_OPERATIONAL_MODE, mode, 0);
}
@@ -1756,8 +1757,7 @@ public class WifiStateMachine extends StateMachine {
/* Socket connection can be lost when we do a graceful shutdown
* or when the driver is hung. Ensure supplicant is stopped here.
*/
- mWifiNative.killSupplicant(mP2pSupported);
- mWifiNative.closeSupplicantConnection();
+ mWifiMonitor.killSupplicant(mP2pSupported);
sendSupplicantConnectionChangedBroadcast(false);
setWifiState(WIFI_STATE_DISABLED);
}
@@ -2139,7 +2139,7 @@ public class WifiStateMachine extends StateMachine {
* Avoids issues with drivers that do not handle interface down
* on a running supplicant properly.
*/
- mWifiNative.killSupplicant(mP2pSupported);
+ mWifiMonitor.killSupplicant(mP2pSupported);
if(mWifiNative.startSupplicant(mP2pSupported)) {
setWifiState(WIFI_STATE_ENABLING);
if (DBG) log("Supplicant start successful");
@@ -2222,7 +2222,7 @@ public class WifiStateMachine extends StateMachine {
case WifiMonitor.SUP_DISCONNECTION_EVENT:
if (++mSupplicantRestartCount <= SUPPLICANT_RESTART_TRIES) {
loge("Failed to setup control channel, restart supplicant");
- mWifiNative.killSupplicant(mP2pSupported);
+ mWifiMonitor.killSupplicant(mP2pSupported);
transitionTo(mInitialState);
sendMessageDelayed(CMD_START_SUPPLICANT, SUPPLICANT_RESTART_INTERVAL_MSECS);
} else {
@@ -2329,9 +2329,7 @@ public class WifiStateMachine extends StateMachine {
}
if (DBG) log("stopping supplicant");
- if (!mWifiNative.stopSupplicant()) {
- loge("Failed to stop supplicant");
- }
+ mWifiMonitor.stopSupplicant();
/* Send ourselves a delayed message to indicate failure after a wait time */
sendMessageDelayed(obtainMessage(CMD_STOP_SUPPLICANT_FAILED,
@@ -3200,6 +3198,7 @@ public class WifiStateMachine extends StateMachine {
class VerifyingLinkState extends State {
@Override
public void enter() {
+ log(getName() + " enter");
setNetworkDetailedState(DetailedState.VERIFYING_POOR_LINK);
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.VERIFYING_POOR_LINK);
sendNetworkStateChangeBroadcast(mLastBssid);
@@ -3209,11 +3208,14 @@ public class WifiStateMachine extends StateMachine {
switch (message.what) {
case WifiWatchdogStateMachine.POOR_LINK_DETECTED:
//stay here
+ log(getName() + " POOR_LINK_DETECTED: no transition");
break;
case WifiWatchdogStateMachine.GOOD_LINK_DETECTED:
+ log(getName() + " GOOD_LINK_DETECTED: transition to captive portal check");
transitionTo(mCaptivePortalCheckState);
break;
default:
+ log(getName() + " what=" + message.what + " NOT_HANDLED");
return NOT_HANDLED;
}
return HANDLED;
@@ -3223,6 +3225,7 @@ public class WifiStateMachine extends StateMachine {
class CaptivePortalCheckState extends State {
@Override
public void enter() {
+ log(getName() + " enter");
setNetworkDetailedState(DetailedState.CAPTIVE_PORTAL_CHECK);
mWifiConfigStore.updateStatus(mLastNetworkId, DetailedState.CAPTIVE_PORTAL_CHECK);
sendNetworkStateChangeBroadcast(mLastBssid);
@@ -3231,6 +3234,7 @@ public class WifiStateMachine extends StateMachine {
public boolean processMessage(Message message) {
switch (message.what) {
case CMD_CAPTIVE_CHECK_COMPLETE:
+ log(getName() + " CMD_CAPTIVE_CHECK_COMPLETE");
try {
mNwService.enableIpv6(mInterfaceName);
} catch (RemoteException re) {
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index cf75381..461dedb 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -120,6 +120,11 @@ public class WifiStateTracker implements NetworkStateTracker {
mWifiManager.captivePortalCheckComplete();
}
+ @Override
+ public void captivePortalCheckCompleted(boolean isCaptivePortal) {
+ // not implemented
+ }
+
/**
* Turn the wireless radio off for a network.
* @param turnOn {@code true} to turn the radio on, {@code false}
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 68a082a..63b94a2 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -858,7 +858,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
}
if (mGroups.clear()) sendP2pPersistentGroupsChangedBroadcast();
- mWifiNative.closeSupplicantConnection();
+ mWifiMonitor.stopMonitoring();
transitionTo(mP2pDisablingState);
break;
case WifiP2pManager.SET_DEVICE_NAME: