Merge "FBE notification improvements - change language for FBE "account locked" notification - use lock icon"
diff --git a/Android.mk b/Android.mk
index 5983b30..ad164e20 100644
--- a/Android.mk
+++ b/Android.mk
@@ -187,6 +187,8 @@
core/java/android/hardware/location/IGeofenceHardware.aidl \
core/java/android/hardware/location/IGeofenceHardwareCallback.aidl \
core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl \
+ core/java/android/hardware/location/IContextHubCallback.aidl \
+ core/java/android/hardware/location/IContextHubService.aidl \
core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl \
core/java/android/hardware/usb/IUsbManager.aidl \
core/java/android/net/ICaptivePortal.aidl \
@@ -417,6 +419,7 @@
telephony/java/com/android/internal/telephony/ISub.aidl \
telephony/java/com/android/internal/telephony/ITelephony.aidl \
telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl \
+ telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl \
telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
wifi/java/android/net/wifi/IWifiManager.aidl \
diff --git a/api/system-current.txt b/api/system-current.txt
index 2fc93fa..0d33503 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -15124,6 +15124,66 @@
package android.hardware.location {
+ public class ContextHubInfo {
+ ctor public ContextHubInfo();
+ method public int describeContents();
+ method public int getId();
+ method public android.hardware.location.MemoryRegion[] getMemoryRegions();
+ method public java.lang.String getName();
+ method public float getPeakMips();
+ method public float getPeakPowerDrawMw();
+ method public int getPlatformVersion();
+ method public float getSleepPowerDrawMw();
+ method public int getStaticSwVersion();
+ method public float getStoppedPowerDrawMw();
+ method public int[] getSupportedSensors();
+ method public java.lang.String getToolchain();
+ method public int getToolchainVersion();
+ method public java.lang.String getVendor();
+ method public void setId(int);
+ method public void setMemoryRegions(android.hardware.location.MemoryRegion[]);
+ method public void setName(java.lang.String);
+ method public void setPeakMips(float);
+ method public void setPeakPowerDrawMw(float);
+ method public void setPlatformVersion(int);
+ method public void setSleepPowerDrawMw(float);
+ method public void setStaticSwVersion(int);
+ method public void setStoppedPowerDrawMw(float);
+ method public void setSupportedSensors(int[]);
+ method public void setToolchain(java.lang.String);
+ method public void setToolchainVersion(int);
+ method public void setVendor(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubInfo> CREATOR;
+ }
+
+ public final class ContextHubManager {
+ method public java.lang.Integer[] findNanoAppOnHub(int, android.hardware.location.NanoAppFilter);
+ method public int[] getContexthubHandles();
+ method public android.hardware.location.ContextHubInfo getContexthubInfo(int);
+ method public android.hardware.location.NanoAppInstanceInfo getNanoAppInstanceInfo(int);
+ method public int loadNanoApp(int, android.hardware.location.NanoApp);
+ method public int sendMessage(int, int, android.hardware.location.ContextHubMessage);
+ method public int unloadNanoApp(int);
+ field public static final int ANY_HUB = -1; // 0xffffffff
+ field public static final int MSG_DATA_SEND = 3; // 0x3
+ field public static final int MSG_LOAD_NANO_APP = 1; // 0x1
+ field public static final int MSG_UNLOAD_NANO_APP = 2; // 0x2
+ }
+
+ public class ContextHubMessage {
+ ctor public ContextHubMessage(int, int, byte[]);
+ method public int describeContents();
+ method public byte[] getData();
+ method public int getMsgType();
+ method public int getVersion();
+ method public void setMsgData(byte[]);
+ method public void setMsgType(int);
+ method public void setVersion(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.hardware.location.ContextHubMessage> CREATOR;
+ }
+
public final class GeofenceHardware {
ctor public GeofenceHardware(android.hardware.location.IGeofenceHardware);
method public boolean addGeofence(int, int, android.hardware.location.GeofenceHardwareRequest, android.hardware.location.GeofenceHardwareCallback);
@@ -15240,6 +15300,89 @@
method public abstract void onMonitoringSystemChange(android.hardware.location.GeofenceHardwareMonitorEvent) throws android.os.RemoteException;
}
+ public class MemoryRegion implements android.os.Parcelable {
+ ctor public MemoryRegion(android.os.Parcel);
+ method public int describeContents();
+ method public int getCapacityBytes();
+ method public int getFreeCapacityBytes();
+ method public boolean isExecutable();
+ method public boolean isReadable();
+ method public boolean isWritable();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.hardware.location.MemoryRegion> CREATOR;
+ }
+
+ public class NanoApp {
+ ctor public NanoApp();
+ method public int describeContents();
+ method public byte[] getAppBinary();
+ method public int getAppId();
+ method public int getAppVersion();
+ method public java.lang.String getName();
+ method public int getNeededExecMemBytes();
+ method public int getNeededReadMemBytes();
+ method public int[] getNeededSensors();
+ method public int getNeededWriteMemBytes();
+ method public int[] getOutputEvents();
+ method public java.lang.String getPublisher();
+ method public void setAppBinary(byte[]);
+ method public void setAppId(int);
+ method public void setAppVersion(int);
+ method public void setName(java.lang.String);
+ method public void setNeededExecMemBytes(int);
+ method public void setNeededReadMemBytes(int);
+ method public void setNeededSensors(int[]);
+ method public void setNeededWriteMemBytes(int);
+ method public void setOutputEvents(int[]);
+ method public void setPublisher(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.hardware.location.NanoApp> CREATOR;
+ }
+
+ public class NanoAppFilter {
+ ctor public NanoAppFilter(long, int, int, long);
+ method public int describeContents();
+ method public boolean testMatch(android.hardware.location.NanoAppInstanceInfo);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final int APP_ANY = -1; // 0xffffffff
+ field public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppFilter> CREATOR;
+ field public static final int FLAGS_VERSION_ANY = -1; // 0xffffffff
+ field public static final int FLAGS_VERSION_GREAT_THAN = 2; // 0x2
+ field public static final int FLAGS_VERSION_LESS_THAN = 4; // 0x4
+ field public static final int FLAGS_VERSION_STRICTLY_EQUAL = 8; // 0x8
+ field public static final int HUB_ANY = -1; // 0xffffffff
+ field public static final int VENDOR_ANY = -1; // 0xffffffff
+ }
+
+ public class NanoAppInstanceInfo {
+ ctor public NanoAppInstanceInfo();
+ method public int describeContents();
+ method public int getAppId();
+ method public int getAppVersion();
+ method public int getContexthubId();
+ method public int getHandle();
+ method public java.lang.String getName();
+ method public int getNeededExecMemBytes();
+ method public int getNeededReadMemBytes();
+ method public int[] getNeededSensors();
+ method public int getNeededWriteMemBytes();
+ method public int[] getOutputEvents();
+ method public java.lang.String getPublisher();
+ method public void setAppId(int);
+ method public void setAppVersion(int);
+ method public void setContexthubId(int);
+ method public void setHandle(int);
+ method public void setName(java.lang.String);
+ method public void setNeededExecMemBytes(int);
+ method public void setNeededReadMemBytes(int);
+ method public void setNeededSensors(int[]);
+ method public void setNeededWriteMemBytes(int);
+ method public void setOutputEvents(int[]);
+ method public void setPublisher(java.lang.String);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.hardware.location.NanoAppInstanceInfo> CREATOR;
+ }
+
}
package android.hardware.radio {
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 7a0e7f6..fa0fbd1 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -35,10 +35,16 @@
* 'which' is some combination of:
* FLAG_SET_SYSTEM
* FLAG_SET_LOCK
+ *
+ * A 'null' cropHint rectangle is explicitly permitted as a sentinel for "whatever
+ * the source image's bounding rect is."
+ *
+ * The completion callback's "onWallpaperChanged()" method is invoked when the
+ * new wallpaper content is ready to display.
*/
ParcelFileDescriptor setWallpaper(String name, in String callingPackage,
- out Bundle extras, int which);
-
+ in Rect cropHint, out Bundle extras, int which, IWallpaperManagerCallback completion);
+
/**
* Set the live wallpaper. This only affects the system wallpaper.
*/
@@ -54,14 +60,14 @@
*/
ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
out Bundle outParams);
-
+
/**
* If the current system wallpaper is a live wallpaper component, return the
* information about that wallpaper. Otherwise, if it is a static image,
* simply return null.
*/
WallpaperInfo getWallpaperInfo();
-
+
/**
* Clear the system wallpaper.
*/
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index f103576..b0ffd21 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -64,6 +64,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Provides access to the system wallpaper. With WallpaperManager, you can
@@ -770,18 +772,26 @@
return 0;
}
final Bundle result = new Bundle();
+ final WallpaperSetCompletion completion = new WallpaperSetCompletion();
try {
Resources resources = mContext.getResources();
/* Set the wallpaper to the default values */
ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(
"res:" + resources.getResourceName(resid),
- mContext.getOpPackageName(), result, which);
+ mContext.getOpPackageName(), null, result, which, completion);
if (fd != null) {
FileOutputStream fos = null;
+ boolean ok = false;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
+ // The 'close()' is the trigger for any server-side image manipulation,
+ // so we must do that before waiting for completion.
+ fos.close();
+ completion.waitForCompletion();
} finally {
+ // Might be redundant but completion shouldn't wait unless the write
+ // succeeded; this is a fallback if it threw past the close+wait.
IoUtils.closeQuietly(fos);
}
}
@@ -876,14 +886,17 @@
return 0;
}
final Bundle result = new Bundle();
+ final WallpaperSetCompletion completion = new WallpaperSetCompletion();
try {
ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
- mContext.getOpPackageName(), result, which);
+ mContext.getOpPackageName(), visibleCropHint, result, which, completion);
if (fd != null) {
FileOutputStream fos = null;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
fullImage.compress(Bitmap.CompressFormat.PNG, 90, fos);
+ fos.close();
+ completion.waitForCompletion();
} finally {
IoUtils.closeQuietly(fos);
}
@@ -990,14 +1003,17 @@
return 0;
}
final Bundle result = new Bundle();
+ final WallpaperSetCompletion completion = new WallpaperSetCompletion();
try {
ParcelFileDescriptor fd = sGlobals.mService.setWallpaper(null,
- mContext.getOpPackageName(), result, which);
+ mContext.getOpPackageName(), visibleCropHint, result, which, completion);
if (fd != null) {
FileOutputStream fos = null;
try {
fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
copyStreamToWallpaperFile(bitmapData, fos);
+ fos.close();
+ completion.waitForCompletion();
} finally {
IoUtils.closeQuietly(fos);
}
@@ -1385,4 +1401,28 @@
return null;
}
+
+ // Private completion callback for setWallpaper() synchronization
+ private class WallpaperSetCompletion extends IWallpaperManagerCallback.Stub {
+ final CountDownLatch mLatch;
+
+ public WallpaperSetCompletion() {
+ mLatch = new CountDownLatch(1);
+ }
+
+ public void waitForCompletion() {
+ try {
+ mLatch.await(30, TimeUnit.SECONDS);
+ } catch (InterruptedException e) {
+ // This might be legit: the crop may take a very long time. Don't sweat
+ // it in that case; we are okay with display lagging behind in order to
+ // keep the caller from locking up indeterminately.
+ }
+ }
+
+ @Override
+ public void onWallpaperChanged() throws RemoteException {
+ mLatch.countDown();
+ }
+ }
}
diff --git a/core/java/android/hardware/input/KeyboardLayout.java b/core/java/android/hardware/input/KeyboardLayout.java
index 584008c..2cafa08 100644
--- a/core/java/android/hardware/input/KeyboardLayout.java
+++ b/core/java/android/hardware/input/KeyboardLayout.java
@@ -16,8 +16,10 @@
package android.hardware.input;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
+import android.util.LocaleList;
import java.util.Locale;
@@ -32,7 +34,8 @@
private final String mLabel;
private final String mCollection;
private final int mPriority;
- private final Locale[] mLocales;
+ @NonNull
+ private final LocaleList mLocales;
private final int mVendorId;
private final int mProductId;
@@ -47,16 +50,12 @@
};
public KeyboardLayout(String descriptor, String label, String collection, int priority,
- Locale[] locales, int vid, int pid) {
+ LocaleList locales, int vid, int pid) {
mDescriptor = descriptor;
mLabel = label;
mCollection = collection;
mPriority = priority;
- if (locales != null) {
- mLocales = locales;
- } else {
- mLocales = new Locale[0];
- }
+ mLocales = locales;
mVendorId = vid;
mProductId = pid;
}
@@ -66,11 +65,7 @@
mLabel = source.readString();
mCollection = source.readString();
mPriority = source.readInt();
- int N = source.readInt();
- mLocales = new Locale[N];
- for (int i = 0; i < N; i++) {
- mLocales[i] = Locale.forLanguageTag(source.readString());
- }
+ mLocales = LocaleList.CREATOR.createFromParcel(source);
mVendorId = source.readInt();
mProductId = source.readInt();
}
@@ -108,7 +103,7 @@
* This may be empty if a locale has not been assigned to this keyboard layout.
* @return The keyboard layout's intended locale.
*/
- public Locale[] getLocales() {
+ public LocaleList getLocales() {
return mLocales;
}
@@ -141,14 +136,7 @@
dest.writeString(mLabel);
dest.writeString(mCollection);
dest.writeInt(mPriority);
- if (mLocales != null) {
- dest.writeInt(mLocales.length);
- for (Locale l : mLocales) {
- dest.writeString(l.toLanguageTag());
- }
- } else {
- dest.writeInt(0);
- }
+ mLocales.writeToParcel(dest, 0);
dest.writeInt(mVendorId);
dest.writeInt(mProductId);
}
diff --git a/core/java/android/hardware/location/ContextHubInfo.aidl b/core/java/android/hardware/location/ContextHubInfo.aidl
new file mode 100644
index 0000000..1a9221a
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubInfo.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+/*
+@hide
+*/
+parcelable ContextHubInfo;
diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java
new file mode 100644
index 0000000..e47c541
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubInfo.java
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * @hide
+ */
+@SystemApi
+public class ContextHubInfo {
+ private int mId;
+ private String mName;
+ private String mVendor;
+ private String mToolchain;
+ private int mPlatformVersion;
+ private int mStaticSwVersion;
+ private int mToolchainVersion;
+ private float mPeakMips;
+ private float mStoppedPowerDrawMw;
+ private float mSleepPowerDrawMw;
+ private float mPeakPowerDrawMw;
+
+ private int[] mSupportedSensors;
+
+ private MemoryRegion[] mMemoryRegions;
+
+ public ContextHubInfo() {
+ }
+
+ /**
+ * get the context hub unique identifer
+ *
+ * @return int - unique system wide identifier
+ */
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * set the context hub unique identifer
+ *
+ * @param id - unique system wide identifier for the hub
+ */
+ public void setId(int id) {
+ mId = id;
+ }
+
+ /**
+ * get a string as a hub name
+ *
+ * @return String - a name for the hub
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * set a string as the hub name
+ *
+ * @param String - the name for the hub
+ */
+ public void setName(String name) {
+ mName = name;
+ }
+
+ /**
+ * get a string as the vendor name
+ *
+ * @return String - a name for the vendor
+ */
+ public String getVendor() {
+ return mVendor;
+ }
+
+ /**
+ * set a string as the vendor name
+ *
+ * @param String - a name for the vendor
+ */
+ public void setVendor(String vendor) {
+ mVendor = vendor;
+ }
+
+ /**
+ * get tool chain string
+ *
+ * @return String - description of the tool chain
+ */
+ public String getToolchain() {
+ return mToolchain;
+ }
+
+ /**
+ * set tool chain string
+ *
+ * @param String - description of the tool chain
+ */
+ public void setToolchain(String toolchain) {
+ mToolchain = toolchain;
+ }
+
+ /**
+ * get platform version
+ *
+ * @return int - platform version number
+ */
+ public int getPlatformVersion() {
+ return mPlatformVersion;
+ }
+
+ /**
+ * set platform version
+ *
+ * @param platformVersion - platform version number
+ */
+ public void setPlatformVersion(int platformVersion) {
+ mPlatformVersion = platformVersion;
+ }
+
+ /**
+ * get static platform version number
+ *
+ * @return int - platform version number
+ */
+ public int getStaticSwVersion() {
+ return mStaticSwVersion;
+ }
+
+ /**
+ * set platform software version
+ *
+ * @param staticSwVersion - platform static s/w version number
+ */
+ public void setStaticSwVersion(int staticSwVersion) {
+ mStaticSwVersion = staticSwVersion;
+ }
+
+ /**
+ * get the tool chain version
+ *
+ * @return int - the tool chain version
+ */
+ public int getToolchainVersion() {
+ return mToolchainVersion;
+ }
+
+ /**
+ * set the tool chain version number
+ *
+ * @param toolchainVersion - tool chain version number
+ */
+ public void setToolchainVersion(int toolchainVersion) {
+ mToolchainVersion = toolchainVersion;
+ }
+
+ /**
+ * get the peak processing mips the hub can support
+ *
+ * @return float - peak MIPS that this hub can deliver
+ */
+ public float getPeakMips() {
+ return mPeakMips;
+ }
+
+ /**
+ * set the peak mips that this hub can support
+ *
+ * @param peakMips - peak mips this hub can deliver
+ */
+ public void setPeakMips(float peakMips) {
+ mPeakMips = peakMips;
+ }
+
+ /**
+ * get the stopped power draw in milliwatts
+ * This assumes that the hub enter a stopped state - which is
+ * different from the sleep state. Latencies on exiting the
+ * sleep state are typically higher and expect to be in multiple
+ * milliseconds.
+ *
+ * @return float - power draw by the hub in stopped state
+ */
+ public float getStoppedPowerDrawMw() {
+ return mStoppedPowerDrawMw;
+ }
+
+ /**
+ * Set the power consumed by the hub in stopped state
+ *
+ * @param stoppedPowerDrawMw - stopped power in milli watts
+ */
+ public void setStoppedPowerDrawMw(float stoppedPowerDrawMw) {
+ mStoppedPowerDrawMw = stoppedPowerDrawMw;
+ }
+
+ /**
+ * get the power draw of the hub in sleep mode. This assumes
+ * that the hub supports a sleep mode in which the power draw is
+ * lower than the power consumed when the hub is actively
+ * processing. As a guideline, assume that the hub should be
+ * able to enter sleep mode if it knows reliably on completion
+ * of some task that the next interrupt/scheduled work item is
+ * at least 250 milliseconds later.
+ *
+ * @return float - sleep power draw in milli watts
+ */
+ public float getSleepPowerDrawMw() {
+ return mSleepPowerDrawMw;
+ }
+
+ /**
+ * Set the sleep power draw in milliwatts
+ *
+ * @param sleepPowerDrawMw - sleep power draw in milliwatts.
+ */
+ public void setSleepPowerDrawMw(float sleepPowerDrawMw) {
+ mSleepPowerDrawMw = sleepPowerDrawMw;
+ }
+
+ /**
+ * get the peak powe draw of the hub. This is the power consumed
+ * by the hub at maximum load.
+ *
+ * @return float - peak power draw
+ */
+ public float getPeakPowerDrawMw() {
+ return mPeakPowerDrawMw;
+ }
+
+ /**
+ * set the peak power draw of the hub
+ *
+ * @param peakPowerDrawMw - peak power draw of the hub in
+ * milliwatts.
+ */
+ public void setPeakPowerDrawMw(float peakPowerDrawMw) {
+ mPeakPowerDrawMw = peakPowerDrawMw;
+ }
+
+ /**
+ * get the sensors supported by this hub
+ *
+ * @return int[] - all the supported sensors on this hub
+ *
+ * @see ContextHubManager
+ */
+ public int[] getSupportedSensors() {
+ return Arrays.copyOf(mSupportedSensors, mSupportedSensors.length);
+ }
+
+ /**
+ * get the various memory regions on this hub
+ *
+ * @return MemoryRegion[] - all the memory regions on this hub
+ *
+ * @see MemoryRegion
+ */
+ public MemoryRegion[] getMemoryRegions() {
+ return Arrays.copyOf(mMemoryRegions, mMemoryRegions.length);
+ }
+
+ /**
+ * set the supported sensors on this hub
+ *
+ * @param supportedSensors - supported sensors on this hub
+ */
+ public void setSupportedSensors(int[] supportedSensors) {
+ mSupportedSensors = Arrays.copyOf(supportedSensors, supportedSensors.length);
+ }
+
+ /**
+ * set memory regions for this hub
+ *
+ * @param memoryRegions - memory regions information
+ *
+ * @see MemoryRegion
+ */
+ public void setMemoryRegions(MemoryRegion[] memoryRegions) {
+ mMemoryRegions = Arrays.copyOf(memoryRegions, memoryRegions.length);
+ }
+
+ private ContextHubInfo(Parcel in) {
+ mId = in.readInt();
+ mName = in.readString();
+ mVendor = in.readString();
+ mToolchain = in.readString();
+ mPlatformVersion = in.readInt();
+ mToolchainVersion = in.readInt();
+ mStaticSwVersion = in.readInt();
+ mPeakMips = in.readFloat();
+ mStoppedPowerDrawMw = in.readFloat();
+ mSleepPowerDrawMw = in.readFloat();
+ mPeakPowerDrawMw = in.readFloat();
+
+ int numSupportedSensors = in.readInt();
+ mSupportedSensors = new int[numSupportedSensors];
+ in.readIntArray(mSupportedSensors);
+ mMemoryRegions = in.createTypedArray(MemoryRegion.CREATOR);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mId);
+ out.writeString(mName);
+ out.writeString(mVendor);
+ out.writeString(mToolchain);
+ out.writeInt(mPlatformVersion);
+ out.writeInt(mToolchainVersion);
+ out.writeInt(mStaticSwVersion);
+ out.writeFloat(mPeakMips);
+ out.writeFloat(mStoppedPowerDrawMw);
+ out.writeFloat(mSleepPowerDrawMw);
+ out.writeFloat(mPeakPowerDrawMw);
+
+ out.writeInt(mSupportedSensors.length);
+ out.writeIntArray(mSupportedSensors);
+ out.writeTypedArray(mMemoryRegions, flags);
+ }
+
+ public static final Parcelable.Creator<ContextHubInfo> CREATOR
+ = new Parcelable.Creator<ContextHubInfo>() {
+ public ContextHubInfo createFromParcel(Parcel in) {
+ return new ContextHubInfo(in);
+ }
+
+ public ContextHubInfo[] newArray(int size) {
+ return new ContextHubInfo[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
new file mode 100644
index 0000000..301b2e4
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+import android.annotation.SystemApi;
+import android.hardware.location.NanoAppInstanceInfo;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.ServiceConnection;
+import android.Manifest;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * A class that exposes the Context hubs on a device to
+ * applicaions.
+ *
+ * Please not that this class is not expected to be used by
+ * unbundled applications. Also, calling applications are
+ * expected to have LOCTION_HARDWARE premissions to use this
+ * class.
+ *
+ * @hide
+ */
+@SystemApi
+public final class ContextHubManager {
+
+ private static final String TAG = "ContextHubManager";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+ private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+ private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+ + HARDWARE_PERMISSION + "' not granted to access ContextHub Hardware";
+
+ private Context mContext;
+ private IContextHubService mContextHubService;
+ private boolean mContextHubConnected;
+
+ /**
+ * A special context hub identifer meaning any possible hub on
+ * the system.
+ */
+ public static final int ANY_HUB = -1;
+ /**
+ * A constant denoting a message to load a a Nano App
+ */
+ public static final int MSG_LOAD_NANO_APP = 1;
+ /**
+ * A constant denoting a message to unload a a Nano App
+ */
+ public static final int MSG_UNLOAD_NANO_APP = 2;
+ /**
+ * A constant denoting a message to send a message
+ */
+ public static final int MSG_DATA_SEND = 3;
+
+
+ /**
+ * Get a handle to all the context hubs in the system
+ * @return array of context hub handles
+ */
+ public int[] getContexthubHandles() {
+ int[] retVal = null;
+ if(mContextHubConnected) {
+ try {
+ retVal = mContextHubService.getContextHubHandles();
+ }catch (RemoteException e) {
+ Log.e (TAG, "Could not fetch context hub handles :" + e.toString());
+ }
+ }
+ return retVal;
+ }
+
+ /**
+ * Get more information about a specific hub.
+ *
+ * @param contexthubHandle Handle of context hub
+ *
+ * @return ContextHubInfo returned information about the hub
+ *
+ * @see ContextHubInfo
+ */
+ public ContextHubInfo getContexthubInfo(int contexthubHandle) {
+ ContextHubInfo retVal = null;
+ if(mContextHubConnected) {
+ try {
+ retVal = mContextHubService.getContextHubInfo(contexthubHandle);
+ }catch (RemoteException e) {
+ Log.e (TAG, "Could not fetch context hub info :" + e.toString());
+ }
+ }
+
+ return(retVal);
+ }
+
+ /**
+ * Load a nanoapp on a specified context hub
+ *
+ * @param hubHandle handle of context hub to load the app on.
+ * @param app the nanoApp to load on the hub
+ *
+ * @return int nanoAppInstance of the loaded nanoApp on success,
+ * -1 otherwise
+ *
+ * @see NanoApp
+ */
+ public int loadNanoApp(int hubHandle, NanoApp app) {
+ int retVal = -1;
+
+ if(mContextHubConnected) {
+ try {
+ retVal = mContextHubService.loadNanoApp(hubHandle, app);
+ }catch (RemoteException e) {
+ Log.e (TAG, "Could not fetch load nanoApp :" + e.toString());
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Unload a specified nanoApp
+ *
+ * @param nanoAppInstanceHandle handle of the nanoApp to load
+ *
+ * @return int 0 on success, -1 otherewise
+ */
+ public int unloadNanoApp(int nanoAppInstanceHandle) {
+ int retVal = -1;
+
+ if(mContextHubConnected) {
+ try {
+ retVal = mContextHubService.unloadNanoApp(nanoAppInstanceHandle);
+ }catch (RemoteException e) {
+ Log.e (TAG, "Could not fetch unload nanoApp :" + e.toString());
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * get information about the nano app instance
+ *
+ * @param nanoAppInstanceHandle handle of the nanoAppInstance
+ *
+ * @return NanoAppInstanceInfo Inforamtion about the nano app
+ * instance.
+ *
+ * @see NanoAppInstanceInfo
+ */
+ public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) {
+ NanoAppInstanceInfo retVal = null;
+
+ if(mContextHubConnected) {
+ try {
+ retVal = mContextHubService.getNanoAppInstanceInfo(nanoAppInstanceHandle);
+ }catch (RemoteException e) {
+ Log.e (TAG, "Could not fetch nanoApp info :" + e.toString());
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Find a specified nano app on the system
+ *
+ * @param hubHandle handle of hub to search for nano app
+ * @param filter filter specifying the search criteria for app
+ *
+ * @see NanoAppFilter
+ *
+ * @return Integer[] Array of handles to any found nano apps
+ */
+ public Integer[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
+ int[] temp;
+ Integer[] retVal = null;
+
+ if(mContextHubConnected) {
+ try {
+ temp = mContextHubService.findNanoAppOnHub(hubHandle, filter);
+ retVal = new Integer[temp.length];
+ for (int i = 0; i < temp.length; i++) {
+ retVal[i] = temp[i];
+ }
+ }catch (RemoteException e) {
+ Log.e (TAG, "Could not query nanoApp instance :" + e.toString());
+ }
+ }
+
+ return retVal;
+ }
+
+ /**
+ * Send a message to a spcific nano app instance on a context
+ * hub
+ *
+ *
+ * @param hubHandle handle of the hub to send the message to
+ * @param nanoAppHandle handle of the nano app to send to
+ * @param msg Message to be sent
+ *
+ * @see ContextHubMessage
+ *
+ * @return int 0 on success, -1 otherwise
+ */
+ public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) {
+ int retVal = -1;
+
+ if(mContextHubConnected) {
+ try {
+ retVal = mContextHubService.sendMessage(hubHandle, nanoAppHandle, msg);
+ }catch (RemoteException e) {
+ Log.e (TAG, "Could not fetch send message :" + e.toString());
+ }
+ }
+
+ return retVal;
+ }
+
+ private void checkPermissions() {
+ mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
+ }
+
+ private IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
+ @Override
+ public void onMessageReceipt(int hubId, int nanoAppId, ContextHubMessage msg) throws RemoteException {
+
+ }
+ };
+
+ private ContextHubManager(Context context) {
+ checkPermissions();
+ mContext = context;
+ mContextHubConnected = false;
+ }
+
+ private ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ mContextHubService = IContextHubService.Stub.asInterface(service);
+ mContextHubConnected = true;
+
+ // Register our Callback
+ try {
+ mContextHubService.registerCallBack(mClientCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not register callback with context hub service :" + e.toString());
+ }
+ Log.d(TAG, "contexthub manager connected to " + name.toString());
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mContextHubService = null;
+ mContextHubConnected = false;
+ Log.d(TAG, "contexthub manager disconnected from " + name.toString());
+ }
+ };
+
+}
diff --git a/core/java/android/hardware/location/ContextHubMessage.aidl b/core/java/android/hardware/location/ContextHubMessage.aidl
new file mode 100644
index 0000000..915f1ec
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubMessage.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+/*
+@hide
+*/
+parcelable ContextHubMessage;
+
diff --git a/core/java/android/hardware/location/ContextHubMessage.java b/core/java/android/hardware/location/ContextHubMessage.java
new file mode 100644
index 0000000..954e97d
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubMessage.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+
+/**
+ * @hide
+ */
+@SystemApi
+public class ContextHubMessage {
+ private int mType;
+ private int mVersion;
+ private byte[]mData;
+
+ /**
+ * Get the message type
+ *
+ * @return int - message type
+ */
+ public int getMsgType() {
+ return mType;
+ }
+
+ /**
+ * get message version
+ *
+ * @return int - message version
+ */
+ public int getVersion() {
+ return mVersion;
+ }
+
+ /**
+ * get message data
+ *
+ * @return byte[] - message data buffer
+ */
+ public byte[] getData() {
+ return Arrays.copyOf(mData, mData.length);
+ }
+
+ /**
+ * set message type
+ *
+ * @param msgType - message type
+ */
+ public void setMsgType(int msgType) {
+ mType = msgType;
+ }
+
+ /**
+ * Set message version
+ *
+ * @param version - message version
+ */
+ public void setVersion(int version) {
+ mVersion = version;
+ }
+
+ /**
+ * set message data
+ *
+ * @param data - message buffer
+ */
+ public void setMsgData(byte[] data) {
+ mData = Arrays.copyOf(data, data.length);
+ }
+
+ /**
+ * Constructor for a context hub message
+ *
+ * @param msgType - message type
+ * @param version - version
+ * @param data - message buffer
+ */
+ public ContextHubMessage(int msgType, int version, byte[] data) {
+ mType = msgType;
+ mVersion = version;
+ mData = Arrays.copyOf(data, data.length);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ private ContextHubMessage(Parcel in) {
+ mType = in.readInt();
+ mVersion = in.readInt();
+ byte[] byteBuffer = new byte[in.readInt()];
+ in.readByteArray(byteBuffer);
+ }
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mType);
+ out.writeInt(mVersion);
+ out.writeInt(mData.length);
+ out.writeByteArray(mData);
+ }
+
+ public static final Parcelable.Creator<ContextHubMessage> CREATOR
+ = new Parcelable.Creator<ContextHubMessage>() {
+ public ContextHubMessage createFromParcel(Parcel in) {
+ return new ContextHubMessage(in);
+ }
+
+ public ContextHubMessage[] newArray(int size) {
+ return new ContextHubMessage[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/location/ContextHubService.java b/core/java/android/hardware/location/ContextHubService.java
new file mode 100644
index 0000000..a2a13c6
--- /dev/null
+++ b/core/java/android/hardware/location/ContextHubService.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+/**
+ * @hide
+ */
+public class ContextHubService extends Service {
+
+ private static final String TAG = "ContextHubService";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static ContextHubService sSingletonInstance;
+ private static final Object sSingletonInstanceLock = new Object();
+
+ private HashMap<Integer, ContextHubInfo> mHubHash;
+ private HashMap<Integer, NanoAppInstanceInfo> mNanoAppHash;
+ private ContextHubInfo[] mContexthubInfo;
+
+
+ private native int nativeSendMessage(int[] header, byte[] data);
+ private native ContextHubInfo[] nativeInitialize();
+
+ private int onMessageReceipt(int[] header, byte[] data) {
+ return 0;
+ }
+ private void initialize() {
+ mContexthubInfo = nativeInitialize();
+
+ mHubHash = new HashMap<Integer, ContextHubInfo>();
+
+ for (int i = 0; i < mContexthubInfo.length; i++) {
+ mHubHash.put(i + 1, mContexthubInfo[i]); // Avoiding zero
+ }
+ }
+
+ private ContextHubService(Context context) {
+ initialize();
+ Log.d(TAG, "Created from " + context.toString());
+ }
+
+ public static ContextHubService getInstance(Context context) {
+ synchronized (sSingletonInstanceLock) {
+ if (sSingletonInstance == null) {
+ sSingletonInstance = new ContextHubService(context);
+ }
+ return sSingletonInstance;
+ }
+ }
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ private final IContextHubService.Stub mBinder = new IContextHubService.Stub() {
+
+ private IContextHubCallback callback;
+
+ @Override
+ public int registerCallBack(IContextHubCallback callback) throws RemoteException{
+ this.callback = callback;
+ return 0;
+ }
+
+ @Override
+ public int[] getContextHubHandles() throws RemoteException {
+ int [] returnArray = new int[mHubHash.size()];
+ int i = 0;
+ for (int key : mHubHash.keySet()) {
+ // Add any filtering here
+ returnArray[i] = key;
+ i++;
+ }
+ return returnArray;
+ }
+
+ @Override
+ public ContextHubInfo getContextHubInfo(int contexthubHandle) throws RemoteException {
+ return mHubHash.get(contexthubHandle);
+ }
+
+ @Override
+ public int loadNanoApp(int hubHandle, NanoApp app) throws RemoteException {
+ if (!mHubHash.containsKey(hubHandle)) {
+ return -1;
+ } else {
+ // Call Native interface here
+ int[] msgHeader = new int[8];
+ msgHeader[0] = ContextHubManager.MSG_LOAD_NANO_APP;
+ msgHeader[1] = app.getAppId();
+ msgHeader[2] = app.getAppVersion();
+ msgHeader[3] = 0; // LOADING_HINTS
+ msgHeader[4] = hubHandle;
+
+ int handle = nativeSendMessage(msgHeader, app.getAppBinary());
+
+ // if successful, add an entry to mNanoAppHash
+
+ if(handle > 0) {
+ return 0;
+ } else {
+
+ return -1;
+ }
+ }
+ }
+
+ @Override
+ public int unloadNanoApp(int nanoAppInstanceHandle) throws RemoteException {
+ if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
+ return -1;
+ } else {
+ NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstanceHandle);
+ // Call Native interface here
+ int[] msgHeader = new int[8];
+ msgHeader[0] = ContextHubManager.MSG_UNLOAD_NANO_APP;
+ msgHeader[1] = info.getContexthubId();
+ msgHeader[2] = info.getHandle();
+
+ int result = nativeSendMessage(msgHeader, null);
+ // if successful, remove the entry in mNanoAppHash
+ if(result == 0) {
+ mNanoAppHash.remove(nanoAppInstanceHandle);
+ }
+ return(result);
+ }
+ }
+
+ @Override
+ public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle) throws RemoteException {
+ // This assumes that all the nanoAppInfo is current. This is reasonable
+ // for the use cases for tightly controlled nanoApps.
+ //
+ if(!mNanoAppHash.containsKey(nanoAppInstanceHandle)) {
+ return(mNanoAppHash.get(nanoAppInstanceHandle));
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) throws RemoteException {
+ ArrayList<Integer> foundInstances = new ArrayList<Integer>();
+
+ for(Integer nanoAppInstance : mNanoAppHash.keySet()) {
+ NanoAppInstanceInfo info = mNanoAppHash.get(nanoAppInstance);
+
+ if(filter.testMatch(info)){
+ foundInstances.add(nanoAppInstance);
+ }
+ }
+
+ int[] retArray = new int[foundInstances.size()];
+ for (int i = 0; i < foundInstances.size(); i++) {
+ retArray[i] = foundInstances.get(i).intValue();
+ }
+
+ return retArray;
+ }
+
+ @Override
+ public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage msg) throws RemoteException {
+ int[] msgHeader = new int[8];
+ msgHeader[0] = ContextHubManager.MSG_DATA_SEND;
+ msgHeader[1] = hubHandle;
+ msgHeader[2] = nanoAppHandle;
+ msgHeader[3] = msg.getMsgType();
+ msgHeader[4] = msg.getVersion();
+
+ return (nativeSendMessage(msgHeader, msg.getData()));
+ }
+ };
+}
diff --git a/core/java/android/hardware/location/IContextHubCallback.aidl b/core/java/android/hardware/location/IContextHubCallback.aidl
new file mode 100644
index 0000000..45b1ef4
--- /dev/null
+++ b/core/java/android/hardware/location/IContextHubCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+import android.hardware.location.ContextHubMessage;
+
+/** @hide */
+oneway interface IContextHubCallback {
+ void onMessageReceipt(int hubId, int nanoAppId, in ContextHubMessage msg);
+}
diff --git a/core/java/android/hardware/location/IContextHubService.aidl b/core/java/android/hardware/location/IContextHubService.aidl
new file mode 100644
index 0000000..b2db0b2
--- /dev/null
+++ b/core/java/android/hardware/location/IContextHubService.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+// Declare any non-default types here with import statements
+import android.hardware.location.ContextHubMessage;
+import android.hardware.location.ContextHubInfo;
+import android.hardware.location.NanoApp;
+import android.hardware.location.NanoAppInstanceInfo;
+import android.hardware.location.NanoAppFilter;
+import android.hardware.location.IContextHubCallback;
+
+/** @hide */
+interface IContextHubService {
+
+ // register a callback to receive messages
+ int registerCallBack(in IContextHubCallback callback);
+
+ // Gets a list of available context hub handles
+ int[] getContextHubHandles();
+
+ // Get the properties of a hub
+ ContextHubInfo getContextHubInfo(int contextHubHandle);
+
+ // Load a nanoapp on a specified context hub
+ int loadNanoApp(int hubHandle, in NanoApp app);
+
+ // Unload a nanoapp instance
+ int unloadNanoApp(int nanoAppInstanceHandle);
+
+ // get information about a nanoAppInstance
+ NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppInstanceHandle);
+
+ // find all nanoApp instances matching some filter
+ int[] findNanoAppOnHub(int hubHandle, in NanoAppFilter filter);
+
+ // send a message to a nanoApp
+ int sendMessage(int hubHandle, int nanoAppHandle, in ContextHubMessage msg);
+}
diff --git a/core/java/android/hardware/location/MemoryRegion.java b/core/java/android/hardware/location/MemoryRegion.java
new file mode 100644
index 0000000..e8c7615
--- /dev/null
+++ b/core/java/android/hardware/location/MemoryRegion.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+
+@SystemApi
+public class MemoryRegion implements Parcelable{
+
+ private int mSizeBytes;
+ private int mSizeBytesFree;
+ private boolean mIsReadable;
+ private boolean mIsWritable;
+ private boolean mIsExecutable;
+
+ /**
+ * get the capacity of the memory region in bytes
+ *
+ * @return int - the memory capacity in bytes
+ */
+ public int getCapacityBytes() {
+ return mSizeBytes;
+ }
+
+ /**
+ * get the free capacity of the memory region in bytes
+ *
+ * @return int - free bytes
+ */
+ public int getFreeCapacityBytes() {
+ return mSizeBytesFree;
+ }
+
+ /**
+ * Is the memory readable
+ *
+ * @return boolean - true if memory is readable, false otherwise
+ */
+ public boolean isReadable() {
+ return mIsReadable;
+ }
+
+ /**
+ * Is the memory writable
+ *
+ * @return boolean - true if memory is writable, false otherwise
+ */
+ public boolean isWritable() {
+ return mIsWritable;
+ }
+
+ /**
+ * Is the memory executable
+ *
+ * @return boolean - true if memory is executable, false
+ * otherwise
+ */
+ public boolean isExecutable() {
+ return mIsExecutable;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mSizeBytes);
+ dest.writeInt(mSizeBytesFree);
+ dest.writeInt(mIsReadable ? 1 : 0);
+ dest.writeInt(mIsWritable ? 1 : 0);
+ dest.writeInt(mIsExecutable ? 1 : 0);
+ }
+
+ public MemoryRegion(Parcel source) {
+ mSizeBytes = source.readInt();
+ mSizeBytesFree = source.readInt();
+ mIsReadable = source.readInt() != 0;
+ mIsWritable = source.readInt() != 0;
+ mIsExecutable = source.readInt() != 0;
+ }
+
+ public static final Parcelable.Creator<MemoryRegion> CREATOR
+ = new Parcelable.Creator<MemoryRegion>() {
+ public MemoryRegion createFromParcel(Parcel in) {
+ return new MemoryRegion(in);
+ }
+
+ public MemoryRegion[] newArray(int size) {
+ return new MemoryRegion[size];
+ }
+ };
+
+}
diff --git a/core/java/android/hardware/location/NanoApp.aidl b/core/java/android/hardware/location/NanoApp.aidl
new file mode 100644
index 0000000..d32c44a
--- /dev/null
+++ b/core/java/android/hardware/location/NanoApp.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+/*
+@hide
+*/
+parcelable NanoApp;
diff --git a/core/java/android/hardware/location/NanoApp.java b/core/java/android/hardware/location/NanoApp.java
new file mode 100644
index 0000000..36d181f
--- /dev/null
+++ b/core/java/android/hardware/location/NanoApp.java
@@ -0,0 +1,290 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class describing nano apps.
+ * A nano app is a piece of executable code that can be
+ * downloaded onto a specific architecture. These are targtted
+ * for low power compute domains on a device.
+ *
+ * Nano apps are expected to be used only by bundled apps only
+ * at this time.
+ *
+ * @hide
+ */
+@SystemApi
+public class NanoApp {
+ private String mPublisher;
+ private String mName;
+
+ private int mAppId;
+ private int mAppVersion;
+
+ private int mNeededReadMemBytes;
+ private int mNeededWriteMemBytes;
+ private int mNeededExecMemBytes;
+
+ private int[] mNeededSensors;
+ private int[] mOutputEvents;
+ private byte[] mAppBinary;
+
+ public NanoApp() {
+ }
+
+ /**
+ * Set the publisher name
+ *
+ * @param publisher name of the publisher of this nano app
+ */
+ public void setPublisher(String publisher) {
+ mPublisher = publisher;
+ }
+
+ /**
+ * set the name of the app
+ *
+ * @param name name of the app
+ */
+ public void setName(String name) {
+ mName = name;
+ }
+
+ /**
+ * set the app identifier
+ *
+ * @param appId add identifier
+ */
+ public void setAppId(int appId) {
+ mAppId = appId;
+ }
+
+ /**
+ * Set the app version
+ *
+ * @param appVersion app version
+ */
+ public void setAppVersion(int appVersion) {
+ mAppVersion = appVersion;
+ }
+
+ /**
+ * set memory needed as read only
+ *
+ * @param neededReadMemBytes
+ * read only memory needed in bytes
+ */
+ public void setNeededReadMemBytes(int neededReadMemBytes) {
+ mNeededReadMemBytes = neededReadMemBytes;
+ }
+
+ /**
+ * set writable memory needed in bytes
+ *
+ * @param neededWriteMemBytes
+ * writable memory needed in bytes
+ */
+ public void setNeededWriteMemBytes(int neededWriteMemBytes) {
+ mNeededWriteMemBytes = neededWriteMemBytes;
+ }
+
+ /**
+ * set executable memory needed
+ *
+ * @param neededExecMemBytes
+ * executable memory needed in bytes
+ */
+ public void setNeededExecMemBytes(int neededExecMemBytes) {
+ mNeededExecMemBytes = neededExecMemBytes;
+ }
+
+ /**
+ * set the sensors needed for this app
+ *
+ * @param neededSensors
+ * needed Sensors
+ */
+ public void setNeededSensors(int[] neededSensors) {
+ mNeededSensors = neededSensors;
+ }
+
+ public void setOutputEvents(int[] outputEvents) {
+ mOutputEvents = outputEvents;
+ }
+
+ /**
+ * set output events returned by the nano app
+ *
+ * @param appBinary generated events
+ */
+ public void setAppBinary(byte[] appBinary) {
+ mAppBinary = appBinary;
+ }
+
+
+ /**
+ * get the publisher name
+ *
+ * @return publisher name
+ */
+ public String getPublisher() {
+ return mPublisher;
+ }
+
+ /**
+ * get the name of the app
+ *
+ * @return app name
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * get the identifier of the app
+ *
+ * @return identifier for this app
+ */
+ public int getAppId() {
+ return mAppId;
+ }
+
+ /**
+ * get the app version
+ *
+ * @return app version
+ */
+ public int getAppVersion() {
+ return mAppVersion;
+ }
+
+ /**
+ * get the ammount of readable memory needed by this app
+ *
+ * @return readable memory needed in bytes
+ */
+ public int getNeededReadMemBytes() {
+ return mNeededReadMemBytes;
+ }
+
+ /**
+ * get the ammount og writable memory needed in bytes
+ *
+ * @return writable memory needed in bytes
+ */
+ public int getNeededWriteMemBytes() {
+ return mNeededWriteMemBytes;
+ }
+
+ /**
+ * executable memory needed in bytes
+ *
+ * @return executable memory needed in bytes
+ */
+ public int getNeededExecMemBytes() {
+ return mNeededExecMemBytes;
+ }
+
+ /**
+ * get the sensors needed by this app
+ *
+ * @return sensors needed
+ */
+ public int[] getNeededSensors() {
+ return mNeededSensors;
+ }
+
+ /**
+ * get the events generated by this app
+ *
+ * @return generated events
+ */
+ public int[] getOutputEvents() {
+ return mOutputEvents;
+ }
+
+ /**
+ * get the binary for this app
+ *
+ * @return app binary
+ */
+ public byte[] getAppBinary() {
+ return mAppBinary;
+ }
+
+ private NanoApp(Parcel in) {
+ mPublisher = in.readString();
+ mName = in.readString();
+
+ mAppId = in.readInt();
+ mAppVersion = in.readInt();
+ mNeededReadMemBytes = in.readInt();
+ mNeededWriteMemBytes = in.readInt();
+ mNeededExecMemBytes = in.readInt();
+
+ int mNeededSensorsLength = in.readInt();
+ mNeededSensors = new int[mNeededSensorsLength];
+ in.readIntArray(mNeededSensors);
+
+ int mOutputEventsLength = in.readInt();
+ mOutputEvents = new int[mOutputEventsLength];
+ in.readIntArray(mOutputEvents);
+
+ int binaryLength = in.readInt();
+ mAppBinary = new byte[binaryLength];
+ in.readByteArray(mAppBinary);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mPublisher);
+ out.writeString(mName);
+ out.writeInt(mAppId);
+ out.writeInt(mAppVersion);
+ out.writeInt(mNeededReadMemBytes);
+ out.writeInt(mNeededWriteMemBytes);
+ out.writeInt(mNeededExecMemBytes);
+
+ out.writeInt(mNeededSensors.length);
+ out.writeIntArray(mNeededSensors);
+
+ out.writeInt(mOutputEvents.length);
+ out.writeIntArray(mOutputEvents);
+
+ out.writeInt(mAppBinary.length);
+ out.writeByteArray(mAppBinary);
+ }
+
+ public static final Parcelable.Creator<NanoApp> CREATOR
+ = new Parcelable.Creator<NanoApp>() {
+ public NanoApp createFromParcel(Parcel in) {
+ return new NanoApp(in);
+ }
+
+ public NanoApp[] newArray(int size) {
+ return new NanoApp[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/location/NanoAppFilter.aidl b/core/java/android/hardware/location/NanoAppFilter.aidl
new file mode 100644
index 0000000..cc6d475
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppFilter.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+/*
+@hide
+*/
+parcelable NanoAppFilter;
diff --git a/core/java/android/hardware/location/NanoAppFilter.java b/core/java/android/hardware/location/NanoAppFilter.java
new file mode 100644
index 0000000..ac341e4
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppFilter.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+@SystemApi
+public class NanoAppFilter {
+
+ // The appId, can be set to APP_ID_ANY
+ private long mAppId;
+
+ // Version to filter apps
+ private int mAppVersion;
+
+ // filtering spec for version
+ private int mVersionRestrictionMask;
+
+ // If APP_ID is any, then a match is performef with the vendor mask
+ private long mAppIdVendorMask;
+
+ // Id of the context hub this instance is expected on
+ private int mContextHubId;
+
+ /**
+ * Flag indicating any version. With this flag set, all versions shall match provided version.
+ */
+ public static final int FLAGS_VERSION_ANY = -1;
+ /**
+ * If this flag is set, only versions strictly greater than the version specified shall match.
+ */
+ public static final int FLAGS_VERSION_GREAT_THAN = 2;
+ /**
+ * If this flag is set, only versions strictly less than the version specified shall match.
+ */
+ public static final int FLAGS_VERSION_LESS_THAN = 4;
+ public static final int FLAGS_VERSION_STRICTLY_EQUAL = 8;
+
+ /**
+ * If this flag is set, only versions strictly equal to the version specified shall match.
+ */
+ public static final int APP_ANY = -1;
+
+ /**
+ * If this flag is set, all vendors shall match.
+ */
+ public static final int VENDOR_ANY = -1;
+
+ /**
+ * If this flag is set, any hub shall match.
+ */
+ public static final int HUB_ANY = -1;
+
+ private NanoAppFilter(Parcel in) {
+ mAppId = in.readLong();
+ mAppVersion = in.readInt();
+ mVersionRestrictionMask = in.readInt();
+ mAppIdVendorMask = in.readInt();
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+
+ out.writeLong(mAppId);
+ out.writeInt(mAppVersion);
+ out.writeInt(mVersionRestrictionMask);
+ out.writeLong(mAppIdVendorMask);
+ }
+
+ /**
+ * Create a filter
+ *
+ * @param appId application id
+ * @param appVersion application version
+ * @param versionMask version
+ * @param vendorMask vendor
+ */
+ public NanoAppFilter(long appId, int appVersion, int versionMask, long vendorMask) {
+ mAppId = appId;
+ mAppVersion = appVersion;
+ mVersionRestrictionMask = versionMask;
+ mAppIdVendorMask = vendorMask;
+ }
+
+ private boolean versionsMatch(int versionRestrictionMask, int expected, int actual){
+ // some refactoring of version restriction mask is needed, until then, return all
+ return true;
+ }
+ /**
+ *
+ * @param nano app instance info
+ *
+ * @return true if this is a match, false otherwise
+ */
+ public boolean testMatch(NanoAppInstanceInfo info) {
+ if ((mContextHubId == HUB_ANY || info.getContexthubId() == mContextHubId) &&
+ (mAppId == APP_ANY || info.getAppId() == mAppId) &&
+ // (mAppIdVendorMask == VENDOR_ANY) TODO : Expose Vendor mask cleanly
+ (versionsMatch(mVersionRestrictionMask, mAppVersion, info.getAppVersion()))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static final Parcelable.Creator<NanoAppFilter> CREATOR
+ = new Parcelable.Creator<NanoAppFilter>() {
+ public NanoAppFilter createFromParcel(Parcel in) {
+ return new NanoAppFilter(in);
+ }
+
+ public NanoAppFilter[] newArray(int size) {
+ return new NanoAppFilter[size];
+ }
+ };
+}
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.aidl b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl
new file mode 100644
index 0000000..c8c40d7
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.aidl
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+/*
+@hide
+*/
+parcelable NanoAppInstanceInfo;
\ No newline at end of file
diff --git a/core/java/android/hardware/location/NanoAppInstanceInfo.java b/core/java/android/hardware/location/NanoAppInstanceInfo.java
new file mode 100644
index 0000000..ac62919
--- /dev/null
+++ b/core/java/android/hardware/location/NanoAppInstanceInfo.java
@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2016 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.hardware.location;
+
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+@SystemApi
+public class NanoAppInstanceInfo {
+ private String mPublisher;
+ private String mName;
+
+ private int mAppId;
+ private int mAppVersion;
+
+ private int mNeededReadMemBytes;
+ private int mNeededWriteMemBytes;
+ private int mNeededExecMemBytes;
+
+ private int[] mNeededSensors;
+ private int[] mOutputEvents;
+
+ private int mContexthubId;
+ private int mHandle;
+
+ public NanoAppInstanceInfo() {
+ }
+
+ /**
+ * get the publisher of this app
+ *
+ * @return String - name of the publisher
+ */
+ public String getPublisher() {
+ return mPublisher;
+ }
+
+
+ /**
+ * set the publisher name for the app
+ *
+ * @param publisher - name of the publisher
+ */
+ public void setPublisher(String publisher) {
+ mPublisher = publisher;
+ }
+
+ /**
+ * get the name of the app
+ *
+ * @return String - name of the app
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * set the name of the app
+ *
+ * @param name - name of the app
+ */
+ public void setName(String name) {
+ mName = name;
+ }
+
+ /**
+ * Get the application identifier
+ *
+ * @return int - application identifier
+ */
+ public int getAppId() {
+ return mAppId;
+ }
+
+ /**
+ * Set the application identifier
+ *
+ * @param appId - application identifier
+ */
+ public void setAppId(int appId) {
+ mAppId = appId;
+ }
+
+ /**
+ * Set the application version
+ *
+ * @return int - version of the app
+ */
+ public int getAppVersion() {
+ return mAppVersion;
+ }
+
+ /**
+ * Set the application version
+ *
+ * @param appVersion - version of the app
+ */
+ public void setAppVersion(int appVersion) {
+ mAppVersion = appVersion;
+ }
+
+ /**
+ * Get the read memory needed by the app
+ *
+ * @return int - readable memory needed in bytes
+ */
+ public int getNeededReadMemBytes() {
+ return mNeededReadMemBytes;
+ }
+
+ /**
+ * Set the read memory needed by the app
+ *
+ * @param neededReadMemBytes - readable Memory needed in bytes
+ */
+ public void setNeededReadMemBytes(int neededReadMemBytes) {
+ mNeededReadMemBytes = neededReadMemBytes;
+ }
+
+ /**
+ * get writable memory needed by the app
+ *
+ * @return int - writable memory needed by the app
+ */
+ public int getNeededWriteMemBytes() {
+ return mNeededWriteMemBytes;
+ }
+
+ /**
+ * set writable memory needed by the app
+ *
+ * @param neededWriteMemBytes - writable memory needed by the
+ * app
+ */
+ public void setNeededWriteMemBytes(int neededWriteMemBytes) {
+ mNeededWriteMemBytes = neededWriteMemBytes;
+ }
+
+ /**
+ * get executable memory needed by the app
+ *
+ * @return int - executable memory needed by the app
+ */
+ public int getNeededExecMemBytes() {
+ return mNeededExecMemBytes;
+ }
+
+ /**
+ * set executable memory needed by the app
+ *
+ * @param neededExecMemBytes - executable memory needed by the
+ * app
+ */
+ public void setNeededExecMemBytes(int neededExecMemBytes) {
+ mNeededExecMemBytes = neededExecMemBytes;
+ }
+
+ /**
+ * Get the sensors needed by this app
+ *
+ * @return int[] all the required sensors needed by this app
+ */
+ public int[] getNeededSensors() {
+ return mNeededSensors;
+ }
+
+ /**
+ * set the sensors needed by this app
+ *
+ * @param neededSensors - all the sensors needed by this app
+ */
+ public void setNeededSensors(int[] neededSensors) {
+ mNeededSensors = neededSensors;
+ }
+
+ /**
+ * get the events generated by this app
+ *
+ * @return all the events that can be generated by this app
+ */
+ public int[] getOutputEvents() {
+ return mOutputEvents;
+ }
+
+ /**
+ * set the output events that can be generated by this app
+ *
+ * @param outputEvents - the events that may be generated by
+ * this app
+ */
+ public void setOutputEvents(int[] outputEvents) {
+ mOutputEvents = outputEvents;
+ }
+
+ /**
+ * get the context hub identifier
+ *
+ * @return int - system unique hub identifier
+ */
+ public int getContexthubId() {
+ return mContexthubId;
+ }
+
+ /**
+ * set the context hub identifier
+ *
+ * @param contexthubId - system wide unique identifier
+ */
+ public void setContexthubId(int contexthubId) {
+ mContexthubId = contexthubId;
+ }
+
+ /**
+ * get a handle to the nano app instance
+ *
+ * @return int - handle to this instance
+ */
+ public int getHandle() {
+ return mHandle;
+ }
+
+ /**
+ * set the handle for an app instance
+ *
+ * @param handle - handle to this instance
+ */
+ public void setHandle(int handle) {
+ mHandle = handle;
+ }
+
+
+ private NanoAppInstanceInfo(Parcel in) {
+ mPublisher = in.readString();
+ mName = in.readString();
+
+ mAppId = in.readInt();
+ mAppVersion = in.readInt();
+ mNeededReadMemBytes = in.readInt();
+ mNeededWriteMemBytes = in.readInt();
+ mNeededExecMemBytes = in.readInt();
+
+ int mNeededSensorsLength = in.readInt();
+ mNeededSensors = new int[mNeededSensorsLength];
+ in.readIntArray(mNeededSensors);
+
+ int mOutputEventsLength = in.readInt();
+ mOutputEvents = new int[mOutputEventsLength];
+ in.readIntArray(mOutputEvents);
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mPublisher);
+ out.writeString(mName);
+ out.writeInt(mAppId);
+ out.writeInt(mAppVersion);
+ out.writeInt(mContexthubId);
+ out.writeInt(mNeededReadMemBytes);
+ out.writeInt(mNeededWriteMemBytes);
+ out.writeInt(mNeededExecMemBytes);
+
+ out.writeInt(mNeededSensors.length);
+ out.writeIntArray(mNeededSensors);
+
+ out.writeInt(mOutputEvents.length);
+ out.writeIntArray(mOutputEvents);
+
+ }
+
+ public static final Parcelable.Creator<NanoAppInstanceInfo> CREATOR
+ = new Parcelable.Creator<NanoAppInstanceInfo>() {
+ public NanoAppInstanceInfo createFromParcel(Parcel in) {
+ return new NanoAppInstanceInfo(in);
+ }
+
+ public NanoAppInstanceInfo[] newArray(int size) {
+ return new NanoAppInstanceInfo[size];
+ }
+ };
+}
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index c3452d5..fa9ff01 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -54,8 +54,7 @@
android:name=".LauncherActivity"
android:theme="@android:style/Theme.NoDisplay"
android:icon="@drawable/ic_files_app"
- android:label="@string/files_label"
- android:enabled="@bool/productivity_device">
+ android:label="@string/files_label">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ff28e15..e8d8c8e 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -18,7 +18,6 @@
<!-- Allow Advanced Devices default value to be customised -->
<bool name="config_defaultAdvancedDevices">false</bool>
- <bool name="productivity_device">true</bool>
<!-- Intentionally unset. Vendors should set this in an overlay. -->
<string name="trusted_quick_viewer_package"></string>
</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index 5ffc435..9309693 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -104,7 +104,6 @@
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
- mProductivityDevice = getResources().getBoolean(R.bool.productivity_device);
mState = (icicle != null)
? icicle.<State>getParcelable(EXTRA_STATE)
: buildState();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 393fdcd..f51f689 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -16,12 +16,11 @@
package com.android.documentsui;
+import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.dirlist.DirectoryFragment.ANIM_NONE;
import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkState;
-import static com.android.documentsui.OperationDialogFragment.DialogType;
-import static com.android.documentsui.OperationDialogFragment.DIALOG_TYPE_UNKNOWN;
import android.app.Activity;
import android.app.FragmentManager;
@@ -45,6 +44,7 @@
import android.widget.Spinner;
import android.widget.Toolbar;
+import com.android.documentsui.OperationDialogFragment.DialogType;
import com.android.documentsui.RecentsProvider.ResumeColumns;
import com.android.documentsui.dirlist.DirectoryFragment;
import com.android.documentsui.model.DocumentInfo;
@@ -256,9 +256,6 @@
pasteFromCb.setEnabled(mClipper.hasItemsToPaste());
- newWindow.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER);
- newWindow.setVisible(mProductivityDevice);
-
Menus.disableHiddenItems(menu, pasteFromCb);
return true;
}
@@ -287,6 +284,14 @@
Metrics.logMultiWindow(this);
Intent intent = LauncherActivity.createLaunchIntent(this);
intent.putExtra(Shared.EXTRA_STACK, (Parcelable) mState.stack);
+
+ // With new multi-window mode we have to pick how we are launched.
+ // By default we'd be launched in-place above the existing app.
+ // By setting launch-to-side ActivityManager will open us to side.
+ if (inMultiWindowMode()) {
+ intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_TO_SIDE);
+ }
+
startActivity(intent);
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
index b3d0cf3..7930c28 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LauncherActivity.java
@@ -74,6 +74,9 @@
private void startTask() {
Intent intent = createLaunchIntent(this);
+
+ // Forward any flags from the original intent.
+ intent.setFlags(getIntent().getFlags());
if (DEBUG) Log.d(TAG, "Starting new task > " + intent.getData());
startActivity(intent);
}
@@ -84,7 +87,7 @@
startActivity(intent);
}
- static Intent createLaunchIntent(Context context) {
+ static final Intent createLaunchIntent(Context context) {
Intent intent = new Intent(context, FilesActivity.class);
intent.setData(buildLaunchUri());
return intent;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 27d4c0e..c7e5ea4 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -35,6 +35,10 @@
public class HumanInteractionClassifier extends Classifier {
private static final String HIC_ENABLE = "HIC_enable";
private static final float FINGER_DISTANCE = 0.1f;
+
+ /** Default value for the HIC_ENABLE setting: 1 - enabled, 0 - disabled */
+ private static final int HIC_ENABLE_DEFAULT = 1;
+
private static HumanInteractionClassifier sInstance = null;
private final Handler mHandler = new Handler();
@@ -101,9 +105,9 @@
}
private void updateConfiguration() {
- mEnableClassifier = Build.IS_DEBUGGABLE && 0 != Settings.Global.getInt(
+ mEnableClassifier = 0 != Settings.Global.getInt(
mContext.getContentResolver(),
- HIC_ENABLE, 0);
+ HIC_ENABLE, HIC_ENABLE_DEFAULT);
}
public void setType(int type) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 76fbebf..b5982c3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12970,6 +12970,9 @@
final StringBuilder sb = new StringBuilder(1024);
appendDropBoxProcessHeaders(process, processName, sb);
+ sb.append("Foreground: ")
+ .append(process.isInterestingToUserLocked() ? "Yes" : "No")
+ .append("\n");
if (activity != null) {
sb.append("Activity: ").append(activity.shortComponentName).append("\n");
}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 573afd6..490764f 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -16,7 +16,9 @@
package com.android.server.input;
+import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.util.LocaleList;
import android.view.Display;
import com.android.internal.inputmethod.InputMethodSubtypeHandle;
import com.android.internal.os.SomeArgs;
@@ -780,8 +782,10 @@
|| layout.getProductId() != d.getProductId()) {
return;
}
- for (Locale l : layout.getLocales()) {
- if (isCompatibleLocale(systemLocale, l)) {
+ final LocaleList locales = layout.getLocales();
+ final int numLocales = locales.size();
+ for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+ if (isCompatibleLocale(systemLocale, locales.get(localeIndex))) {
layouts.add(layout);
break;
}
@@ -799,9 +803,12 @@
final int N = layouts.size();
for (int i = 0; i < N; i++) {
KeyboardLayout layout = layouts.get(i);
- for (Locale l : layout.getLocales()) {
- if (l.getCountry().equals(systemLocale.getCountry())
- && l.getVariant().equals(systemLocale.getVariant())) {
+ final LocaleList locales = layout.getLocales();
+ final int numLocales = locales.size();
+ for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+ final Locale locale = locales.get(localeIndex);
+ if (locale.getCountry().equals(systemLocale.getCountry())
+ && locale.getVariant().equals(systemLocale.getVariant())) {
return layout.getDescriptor();
}
}
@@ -809,8 +816,11 @@
// Then try an exact match of language and country
for (int i = 0; i < N; i++) {
KeyboardLayout layout = layouts.get(i);
- for (Locale l : layout.getLocales()) {
- if (l.getCountry().equals(systemLocale.getCountry())) {
+ final LocaleList locales = layout.getLocales();
+ final int numLocales = locales.size();
+ for (int localeIndex = 0; localeIndex < numLocales; ++localeIndex) {
+ final Locale locale = locales.get(localeIndex);
+ if (locale.getCountry().equals(systemLocale.getCountry())) {
return layout.getDescriptor();
}
}
@@ -1170,7 +1180,7 @@
0);
String languageTags = a.getString(
com.android.internal.R.styleable.KeyboardLayout_locale);
- Locale[] locales = getLocalesFromLanguageTags(languageTags);
+ LocaleList locales = getLocalesFromLanguageTags(languageTags);
int vid = a.getInt(
com.android.internal.R.styleable.KeyboardLayout_vendorId, -1);
int pid = a.getInt(
@@ -1210,16 +1220,12 @@
}
}
- private static Locale[] getLocalesFromLanguageTags(String languageTags) {
+ @NonNull
+ private static LocaleList getLocalesFromLanguageTags(String languageTags) {
if (TextUtils.isEmpty(languageTags)) {
- return new Locale[0];
+ return LocaleList.getEmptyLocaleList();
}
- String[] tags = languageTags.split("\\|");
- Locale[] locales = new Locale[tags.length];
- for (int i = 0; i < tags.length; i++) {
- locales[i] = Locale.forLanguageTag(tags[i]);
- }
- return locales;
+ return LocaleList.forLanguageTags(languageTags.replace('|', ','));
}
/**
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 39983dd..c7d7096 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -42,6 +42,9 @@
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Binder;
@@ -71,6 +74,7 @@
import android.view.IWindowManager;
import android.view.WindowManager;
+import java.io.BufferedOutputStream;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
@@ -96,7 +100,7 @@
public class WallpaperManagerService extends IWallpaperManager.Stub {
static final String TAG = "WallpaperManagerService";
- static final boolean DEBUG = false;
+ static final boolean DEBUG = true;
final Object mLock = new Object[0];
@@ -106,7 +110,8 @@
*/
static final long MIN_WALLPAPER_CRASH_TIME = 10000;
static final int MAX_WALLPAPER_COMPONENT_LOG_LENGTH = 128;
- static final String WALLPAPER = "wallpaper";
+ static final String WALLPAPER = "wallpaper_orig";
+ static final String WALLPAPER_CROP = "wallpaper";
static final String WALLPAPER_INFO = "wallpaper_info.xml";
/**
@@ -120,6 +125,7 @@
final WallpaperData mWallpaper;
final File mWallpaperDir;
final File mWallpaperFile;
+ final File mWallpaperCropFile;
final File mWallpaperInfoFile;
public WallpaperObserver(WallpaperData wallpaper) {
@@ -128,6 +134,7 @@
mWallpaperDir = getWallpaperDir(wallpaper.userId);
mWallpaper = wallpaper;
mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
+ mWallpaperCropFile = new File(mWallpaperDir, WALLPAPER_CROP);
mWallpaperInfoFile = new File(mWallpaperDir, WALLPAPER_INFO);
}
@@ -136,8 +143,10 @@
if (path == null) {
return;
}
+ final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
+ final File changedFile = new File(mWallpaperDir, path);
+
synchronized (mLock) {
- File changedFile = new File(mWallpaperDir, path);
if (mWallpaperFile.equals(changedFile)
|| mWallpaperInfoFile.equals(changedFile)) {
// changing the wallpaper means we'll need to back up the new one
@@ -148,22 +157,111 @@
}
if (mWallpaperFile.equals(changedFile)) {
notifyCallbacksLocked(mWallpaper);
- final boolean written = (event == CLOSE_WRITE || event == MOVED_TO);
if (mWallpaper.wallpaperComponent == null
|| event != CLOSE_WRITE // includes the MOVED_TO case
|| mWallpaper.imageWallpaperPending) {
if (written) {
+ // The image source has finished writing the source image,
+ // so we now produce the crop rect (in the background), and
+ // only publish the new displayable (sub)image as a result
+ // of that work.
+ generateCrop(mWallpaper);
mWallpaper.imageWallpaperPending = false;
+ if (mWallpaper.setComplete != null) {
+ try {
+ mWallpaper.setComplete.onWallpaperChanged();
+ } catch (RemoteException e) {
+ // if this fails we don't really care; the setting app may just
+ // have crashed and that sort of thing is a fact of life.
+ }
+ }
+ bindWallpaperComponentLocked(mImageWallpaper, true,
+ false, mWallpaper, null);
+ saveSettingsLocked(mWallpaper);
}
- bindWallpaperComponentLocked(mImageWallpaper, true,
- false, mWallpaper, null);
- saveSettingsLocked(mWallpaper);
}
}
}
}
}
+ /**
+ * Once a new wallpaper has been written via setWallpaper(...), it needs to be cropped
+ * for display.
+ */
+ private void generateCrop(WallpaperData wallpaper) {
+ boolean success = false;
+ boolean needCrop = false;
+
+ // Analyse the source; needed in multiple cases
+ BitmapFactory.Options options = new BitmapFactory.Options();
+ options.inJustDecodeBounds = true;
+ BitmapFactory.decodeFile(wallpaper.wallpaperFile.getAbsolutePath(), options);
+
+ // Legacy case uses an empty crop rect here, so we just preserve the
+ // source image verbatim
+ if (!wallpaper.cropHint.isEmpty()) {
+ // ...clamp the crop rect to the measured bounds...
+ wallpaper.cropHint.right = Math.min(wallpaper.cropHint.right, options.outWidth);
+ wallpaper.cropHint.bottom = Math.min(wallpaper.cropHint.bottom, options.outHeight);
+ // ...and don't bother cropping if what we're left with is identity
+ needCrop = (options.outHeight >= wallpaper.cropHint.height()
+ && options.outWidth >= wallpaper.cropHint.width());
+ }
+
+ if (!needCrop) {
+ // Simple case: the nominal crop is at least as big as the source image,
+ // so we take the whole thing and just copy the image file directly.
+ if (DEBUG) {
+ Slog.v(TAG, "Null crop of new wallpaper; copying");
+ }
+ success = FileUtils.copyFile(wallpaper.wallpaperFile, wallpaper.cropFile);
+ if (!success) {
+ wallpaper.cropFile.delete();
+ // TODO: fall back to default wallpaper in this case
+ }
+ } else {
+ // Fancy case: the crop is a subrect of the source
+ FileOutputStream f = null;
+ BufferedOutputStream bos = null;
+ try {
+ BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(
+ wallpaper.wallpaperFile.getAbsolutePath(), false);
+ Bitmap cropped = decoder.decodeRegion(wallpaper.cropHint, null);
+ decoder.recycle();
+
+ if (cropped == null) {
+ Slog.e(TAG, "Could not decode new wallpaper");
+ } else {
+ f = new FileOutputStream(wallpaper.cropFile);
+ bos = new BufferedOutputStream(f, 32*1024);
+ cropped.compress(Bitmap.CompressFormat.PNG, 90, bos);
+ bos.flush(); // don't rely on the implicit flush-at-close when noting success
+ success = true;
+ }
+ } catch (IOException e) {
+ if (DEBUG) {
+ Slog.e(TAG, "I/O error decoding crop: " + e.getMessage());
+ }
+ } finally {
+ IoUtils.closeQuietly(bos);
+ IoUtils.closeQuietly(f);
+ }
+ }
+
+ if (!success) {
+ Slog.e(TAG, "Unable to apply new wallpaper");
+ wallpaper.cropFile.delete();
+ }
+
+ if (wallpaper.cropFile.exists()) {
+ boolean didRestorecon = SELinux.restorecon(wallpaper.cropFile.getAbsoluteFile());
+ if (DEBUG) {
+ Slog.v(TAG, "restorecon() of crop file returned " + didRestorecon);
+ }
+ }
+ }
+
final Context mContext;
final IWindowManager mIWindowManager;
final IPackageManager mIPackageManager;
@@ -191,7 +289,8 @@
int userId;
- File wallpaperFile;
+ final File wallpaperFile;
+ final File cropFile;
/**
* Client is currently writing a new image wallpaper.
@@ -199,6 +298,11 @@
boolean imageWallpaperPending;
/**
+ * Callback once the set + crop is finished
+ */
+ IWallpaperManagerCallback setComplete;
+
+ /**
* Resource name if using a picture from the wallpaper gallery
*/
String name = "";
@@ -232,11 +336,26 @@
int width = -1;
int height = -1;
+ /**
+ * The crop hint supplied for displaying a subset of the source image
+ */
+ final Rect cropHint = new Rect(0, 0, 0, 0);
+
final Rect padding = new Rect(0, 0, 0, 0);
WallpaperData(int userId) {
this.userId = userId;
wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
+ cropFile = new File(getWallpaperDir(userId), WALLPAPER_CROP);
+ }
+
+ // Only called in single-threaded boot sequence mode
+ boolean ensureCropExists() {
+ // if the crop file is not present, copy over the source image to use verbatim
+ if (!cropFile.exists()) {
+ return FileUtils.copyFile(wallpaperFile, cropFile);
+ }
+ return true;
}
}
@@ -524,6 +643,9 @@
public void systemRunning() {
if (DEBUG) Slog.v(TAG, "systemReady");
WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
+ if (!wallpaper.ensureCropExists()) {
+ clearWallpaperLocked(false, UserHandle.USER_SYSTEM, null);
+ }
switchWallpaper(wallpaper, null);
wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
wallpaper.wallpaperObserver.startWatching();
@@ -602,6 +724,8 @@
onStoppingUser(userId);
File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
wallpaperFile.delete();
+ File cropFile = new File(getWallpaperDir(userId), WALLPAPER_CROP);
+ cropFile.delete();
File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
wallpaperInfoFile.delete();
}
@@ -653,9 +777,9 @@
if (wallpaper == null) {
return;
}
- File f = new File(getWallpaperDir(userId), WALLPAPER);
- if (f.exists()) {
- f.delete();
+ if (wallpaper.wallpaperFile.exists()) {
+ wallpaper.wallpaperFile.delete();
+ wallpaper.cropFile.delete();
}
final long ident = Binder.clearCallingIdentity();
try {
@@ -844,11 +968,10 @@
outParams.putInt("height", wallpaper.height);
}
wallpaper.callbacks.register(cb);
- File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
- if (!f.exists()) {
+ if (!wallpaper.cropFile.exists()) {
return null;
}
- return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
+ return ParcelFileDescriptor.open(wallpaper.cropFile, MODE_READ_ONLY);
} catch (FileNotFoundException e) {
/* Shouldn't happen as we check to see if the file exists */
Slog.w(TAG, "Error getting wallpaper", e);
@@ -869,8 +992,8 @@
}
@Override
- public ParcelFileDescriptor setWallpaper(String name, String callingPackage, Bundle extras,
- int which) {
+ public ParcelFileDescriptor setWallpaper(String name, String callingPackage,
+ Rect cropHint, Bundle extras, int which, IWallpaperManagerCallback completion) {
checkPermission(android.Manifest.permission.SET_WALLPAPER);
if (which == 0) {
@@ -881,6 +1004,17 @@
return null;
}
+ // "null" means the no-op crop, preserving the full input image
+ if (cropHint == null) {
+ cropHint = new Rect(0, 0, 0, 0);
+ } else {
+ if (cropHint.isEmpty()
+ || cropHint.left < 0
+ || cropHint.top < 0) {
+ return null;
+ }
+ }
+
synchronized (mLock) {
if (DEBUG) Slog.v(TAG, "setWallpaper");
int userId = UserHandle.getCallingUserId();
@@ -890,6 +1024,8 @@
ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper, extras);
if (pfd != null) {
wallpaper.imageWallpaperPending = true;
+ wallpaper.setComplete = completion;
+ wallpaper.cropHint.set(cropHint);
}
return pfd;
} finally {
@@ -1196,6 +1332,12 @@
out.attribute(null, "id", Integer.toString(wallpaper.wallpaperId));
out.attribute(null, "width", Integer.toString(wallpaper.width));
out.attribute(null, "height", Integer.toString(wallpaper.height));
+
+ out.attribute(null, "cropLeft", Integer.toString(wallpaper.cropHint.left));
+ out.attribute(null, "cropTop", Integer.toString(wallpaper.cropHint.top));
+ out.attribute(null, "cropRight", Integer.toString(wallpaper.cropHint.right));
+ out.attribute(null, "cropBottom", Integer.toString(wallpaper.cropHint.bottom));
+
if (wallpaper.padding.left != 0) {
out.attribute(null, "paddingLeft", Integer.toString(wallpaper.padding.left));
}
@@ -1208,6 +1350,7 @@
if (wallpaper.padding.bottom != 0) {
out.attribute(null, "paddingBottom", Integer.toString(wallpaper.padding.bottom));
}
+
out.attribute(null, "name", wallpaper.name);
if (wallpaper.wallpaperComponent != null
&& !wallpaper.wallpaperComponent.equals(mImageWallpaper)) {
@@ -1304,6 +1447,10 @@
wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
wallpaper.height = Integer.parseInt(parser
.getAttributeValue(null, "height"));
+ wallpaper.cropHint.left = getAttributeInt(parser, "cropLeft", 0);
+ wallpaper.cropHint.top = getAttributeInt(parser, "cropTop", 0);
+ wallpaper.cropHint.right = getAttributeInt(parser, "cropRight", 0);
+ wallpaper.cropHint.bottom = getAttributeInt(parser, "cropBottom", 0);
wallpaper.padding.left = getAttributeInt(parser, "paddingLeft", 0);
wallpaper.padding.top = getAttributeInt(parser, "paddingTop", 0);
wallpaper.padding.right = getAttributeInt(parser, "paddingRight", 0);
@@ -1322,6 +1469,7 @@
if (DEBUG) {
Slog.v(TAG, "mWidth:" + wallpaper.width);
Slog.v(TAG, "mHeight:" + wallpaper.height);
+ Slog.v(TAG, "cropRect:" + wallpaper.cropHint);
Slog.v(TAG, "mName:" + wallpaper.name);
Slog.v(TAG, "mNextWallpaperComponent:"
+ wallpaper.nextWallpaperComponent);
@@ -1348,6 +1496,7 @@
if (!success) {
wallpaper.width = -1;
wallpaper.height = -1;
+ wallpaper.cropHint.set(0, 0, 0, 0);
wallpaper.padding.set(0, 0, 0, 0);
wallpaper.name = "";
} else {
@@ -1368,6 +1517,11 @@
if (wallpaper.height < baseSize) {
wallpaper.height = baseSize;
}
+ // and crop, if not previously specified
+ if (wallpaper.cropHint.width() <= 0
+ || wallpaper.cropHint.height() <= 0) {
+ wallpaper.cropHint.set(0, 0, wallpaper.width, wallpaper.height);
+ }
}
private int getMaximumSizeDimension() {
@@ -1431,6 +1585,7 @@
}
}
+ // Restore the named resource bitmap to both source + crop files
boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
String resName = wallpaper.name.substring(4);
@@ -1456,6 +1611,7 @@
int resId = -1;
InputStream res = null;
FileOutputStream fos = null;
+ FileOutputStream cos = null;
try {
Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
Resources r = c.getResources();
@@ -1469,13 +1625,16 @@
res = r.openRawResource(resId);
if (wallpaper.wallpaperFile.exists()) {
wallpaper.wallpaperFile.delete();
+ wallpaper.cropFile.delete();
}
fos = new FileOutputStream(wallpaper.wallpaperFile);
+ cos = new FileOutputStream(wallpaper.cropFile);
byte[] buffer = new byte[32768];
int amt;
while ((amt=res.read(buffer)) > 0) {
fos.write(buffer, 0, amt);
+ cos.write(buffer, 0, amt);
}
// mWallpaperObserver will notice the close and send the change broadcast
@@ -1491,8 +1650,12 @@
IoUtils.closeQuietly(res);
if (fos != null) {
FileUtils.sync(fos);
- IoUtils.closeQuietly(fos);
}
+ if (cos != null) {
+ FileUtils.sync(cos);
+ }
+ IoUtils.closeQuietly(fos);
+ IoUtils.closeQuietly(cos);
}
}
}
@@ -1520,6 +1683,7 @@
pw.print(wallpaper.width);
pw.print(" mHeight=");
pw.println(wallpaper.height);
+ pw.print(" mCropHint="); pw.println(wallpaper.cropHint);
pw.print(" mPadding="); pw.println(wallpaper.padding);
pw.print(" mName="); pw.println(wallpaper.name);
pw.print(" mWallpaperComponent="); pw.println(wallpaper.wallpaperComponent);
diff --git a/telephony/java/android/telephony/ModemActivityInfo.java b/telephony/java/android/telephony/ModemActivityInfo.java
index c65e8ba..84883d8 100644
--- a/telephony/java/android/telephony/ModemActivityInfo.java
+++ b/telephony/java/android/telephony/ModemActivityInfo.java
@@ -48,7 +48,9 @@
mTimestamp = timestamp;
mSleepTimeMs = sleepTimeMs;
mIdleTimeMs = idleTimeMs;
- System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+ if (txTimeMs != null) {
+ System.arraycopy(txTimeMs, 0, mTxTimeMs, 0, Math.min(txTimeMs.length, TX_POWER_LEVELS));
+ }
mRxTimeMs = rxTimeMs;
mEnergyUsed = energyUsed;
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
index 5dffa28..069fcbf 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyDebug.aidl
@@ -16,8 +16,9 @@
package com.android.internal.telephony;
-import android.os.Bundle;
+import com.android.internal.telephony.ITelephonyDebugSubscriber;
+import android.os.Bundle;
/**
* Interface used to interact with the Telephony debug service.
@@ -36,4 +37,7 @@
* @param data optional
*/
void writeEvent(long timestamp, int phoneId, int tag, int param1, int param2, in Bundle data);
+
+ void subscribe(in ITelephonyDebugSubscriber subscriber);
+ void unsubscribe(in ITelephonyDebugSubscriber subscriber);
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl b/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
new file mode 100644
index 0000000..64eb0f1
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/ITelephonyDebugSubscriber.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2016 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.internal.telephony;
+
+import com.android.internal.telephony.TelephonyEvent;
+
+import android.os.Bundle;
+
+/**
+ * Interface used to subscribe for events from Telephony debug service.
+ *
+ * {@hide}
+ */
+oneway interface ITelephonyDebugSubscriber {
+
+ /**
+ * Called when Telephony debug service has events.
+ */
+ void onEvents(in TelephonyEvent[] events);
+}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl b/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
new file mode 100644
index 0000000..1e74b31
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyEvent.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2016 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.internal.telephony;
+
+parcelable TelephonyEvent;
diff --git a/telephony/java/com/android/internal/telephony/TelephonyEvent.java b/telephony/java/com/android/internal/telephony/TelephonyEvent.java
new file mode 100644
index 0000000..26d466d
--- /dev/null
+++ b/telephony/java/com/android/internal/telephony/TelephonyEvent.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2016 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.internal.telephony;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A parcelable used in ITelephonyDebugSubscriber.aidl
+ */
+public class TelephonyEvent implements Parcelable {
+
+ final public long timestamp;
+ final public int phoneId;
+ final public int tag;
+ final public int param1;
+ final public int param2;
+ final public Bundle data;
+
+ public TelephonyEvent(long timestamp, int phoneId, int tag,
+ int param1, int param2, Bundle data) {
+ this.timestamp = timestamp;
+ this.phoneId = phoneId;
+ this.tag = tag;
+ this.param1 = param1;
+ this.param2 = param2;
+ this.data = data;
+ }
+
+ /** Implement the Parcelable interface */
+ public static final Parcelable.Creator<TelephonyEvent> CREATOR
+ = new Parcelable.Creator<TelephonyEvent> (){
+ public TelephonyEvent createFromParcel(Parcel source) {
+ final long timestamp = source.readLong();
+ final int phoneId = source.readInt();
+ final int tag = source.readInt();
+ final int param1 = source.readInt();
+ final int param2 = source.readInt();
+ final Bundle data = source.readBundle();
+ return new TelephonyEvent(timestamp, phoneId, tag, param1, param2, data);
+ }
+
+ public TelephonyEvent[] newArray(int size) {
+ return new TelephonyEvent[size];
+ }
+ };
+
+ /** Implement the Parcelable interface */
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /** Implement the Parcelable interface */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeLong(timestamp);
+ dest.writeInt(phoneId);
+ dest.writeInt(tag);
+ dest.writeInt(param1);
+ dest.writeInt(param2);
+ dest.writeBundle(data);
+ }
+
+ public String toString() {
+ return String.format("%d,%d,%d,%d,%d,%s",
+ timestamp, phoneId, tag, param1, param2, data);
+ }
+}
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml
new file mode 100644
index 0000000..0e2467f
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_fill_state_list_simple.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 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.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#f00" android:state_pressed="true" />
+ <item android:color="#00f" />
+</selector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml
new file mode 100644
index 0000000..7e6c8ce
--- /dev/null
+++ b/tests/VectorDrawableTest/res/color/vector_icon_stroke_state_list_simple.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 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.
+ */
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:color="#00f" android:state_pressed="true" />
+ <item android:color="#f00" />
+</selector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml
new file mode 100644
index 0000000..9f08fe8
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_simple.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2016 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.
+ */
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="64dp"
+ android:width="64dp"
+ android:viewportHeight="24"
+ android:viewportWidth="24" >
+
+ <path
+ android:fillColor="@color/vector_icon_fill_state_list_simple"
+ android:strokeColor="@color/vector_icon_stroke_state_list_simple"
+ android:strokeWidth="3"
+ android:pathData="M16.0,5.0c-1.955.0 -3.83,1.268 -4.5,3.0c-0.67-1.732 -2.547-3.0 -4.5-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207-5.242 9.0-7.971 9.0-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"/>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml
similarity index 100%
rename from tests/VectorDrawableTest/res/drawable/vector_icon_state_list.xml
rename to tests/VectorDrawableTest/res/drawable/vector_icon_state_list_theme.xml
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index a7da286..7172147 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -38,7 +38,8 @@
R.drawable.vector_icon_gradient_1,
R.drawable.vector_icon_gradient_2,
R.drawable.vector_icon_gradient_3,
- R.drawable.vector_icon_state_list,
+ R.drawable.vector_icon_state_list_simple,
+ R.drawable.vector_icon_state_list_theme,
R.drawable.vector_drawable01,
R.drawable.vector_drawable02,
R.drawable.vector_drawable03,