summaryrefslogtreecommitdiff
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/slice/ISliceListener.aidl25
-rw-r--r--core/java/android/app/slice/ISliceManager.aidl11
-rw-r--r--core/java/android/app/slice/Slice.aidl19
-rw-r--r--core/java/android/app/slice/SliceManager.java92
-rw-r--r--core/java/android/app/slice/SliceProvider.java73
-rw-r--r--core/java/android/app/slice/SliceSpec.aidl19
-rw-r--r--core/java/android/app/slice/SliceSpec.java5
7 files changed, 244 insertions, 0 deletions
diff --git a/core/java/android/app/slice/ISliceListener.aidl b/core/java/android/app/slice/ISliceListener.aidl
new file mode 100644
index 000000000000..d293fd46d298
--- /dev/null
+++ b/core/java/android/app/slice/ISliceListener.aidl
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2017, 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.app.slice;
+
+import android.app.slice.ISliceManager;
+import android.app.slice.Slice;
+
+/** @hide */
+oneway interface ISliceListener {
+ void onSliceUpdated(in Slice s);
+}
diff --git a/core/java/android/app/slice/ISliceManager.aidl b/core/java/android/app/slice/ISliceManager.aidl
index 6e52f385bcf7..5f0e542f4b12 100644
--- a/core/java/android/app/slice/ISliceManager.aidl
+++ b/core/java/android/app/slice/ISliceManager.aidl
@@ -16,6 +16,17 @@
package android.app.slice;
+import android.app.slice.ISliceListener;
+import android.app.slice.SliceSpec;
+import android.net.Uri;
+
/** @hide */
interface ISliceManager {
+ void addSliceListener(in Uri uri, String pkg, in ISliceListener listener,
+ in SliceSpec[] specs);
+ void removeSliceListener(in Uri uri, String pkg, in ISliceListener listener);
+ void pinSlice(String pkg, in Uri uri, in SliceSpec[] specs);
+ void unpinSlice(String pkg, in Uri uri);
+ boolean hasSliceAccess(String pkg);
+ SliceSpec[] getPinnedSpecs(in Uri uri, String pkg);
}
diff --git a/core/java/android/app/slice/Slice.aidl b/core/java/android/app/slice/Slice.aidl
new file mode 100644
index 000000000000..e097f9d09a9a
--- /dev/null
+++ b/core/java/android/app/slice/Slice.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, 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.app.slice;
+
+parcelable Slice;
diff --git a/core/java/android/app/slice/SliceManager.java b/core/java/android/app/slice/SliceManager.java
index e99f67632712..f8e19c12b810 100644
--- a/core/java/android/app/slice/SliceManager.java
+++ b/core/java/android/app/slice/SliceManager.java
@@ -17,8 +17,11 @@
package android.app.slice;
import android.annotation.SystemService;
+import android.app.slice.ISliceListener.Stub;
import android.content.Context;
+import android.net.Uri;
import android.os.Handler;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
@@ -36,4 +39,93 @@ public class SliceManager {
mService = ISliceManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.SLICE_SERVICE));
}
+
+ /**
+ */
+ public void addSliceListener(Uri uri, SliceListener listener, SliceSpec[] specs) {
+ try {
+ mService.addSliceListener(uri, mContext.getPackageName(), listener.mStub, specs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ */
+ public void removeSliceListener(Uri uri, SliceListener listener) {
+ try {
+ mService.removeSliceListener(uri, mContext.getPackageName(), listener.mStub);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ */
+ public void pinSlice(Uri uri, SliceSpec[] specs) {
+ try {
+ mService.pinSlice(mContext.getPackageName(), uri, specs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ */
+ public void unpinSlice(Uri uri) {
+ try {
+ mService.unpinSlice(mContext.getPackageName(), uri);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ */
+ public boolean hasSliceAccess() {
+ try {
+ return mService.hasSliceAccess(mContext.getPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ */
+ public SliceSpec[] getPinnedSpecs(Uri uri) {
+ try {
+ return mService.getPinnedSpecs(uri, mContext.getPackageName());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ */
+ public abstract static class SliceListener {
+ private final Handler mHandler;
+
+ /**
+ */
+ public SliceListener() {
+ this(Handler.getMain());
+ }
+
+ /**
+ */
+ public SliceListener(Handler h) {
+ mHandler = h;
+ }
+
+ /**
+ */
+ public abstract void onSliceUpdated(Slice s);
+
+ private final ISliceListener.Stub mStub = new Stub() {
+ @Override
+ public void onSliceUpdated(Slice s) throws RemoteException {
+ mHandler.post(() -> SliceListener.this.onSliceUpdated(s));
+ }
+ };
+ }
}
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index ac5365c35f49..7dcd2fead73f 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -105,6 +105,14 @@ public abstract class SliceProvider extends ContentProvider {
/**
* @hide
*/
+ public static final String METHOD_PIN = "pin";
+ /**
+ * @hide
+ */
+ public static final String METHOD_UNPIN = "unpin";
+ /**
+ * @hide
+ */
public static final String EXTRA_INTENT = "slice_intent";
/**
* @hide
@@ -143,6 +151,18 @@ public abstract class SliceProvider extends ContentProvider {
}
/**
+ * @hide
+ */
+ public void onSlicePinned(Uri sliceUri) {
+ }
+
+ /**
+ * @hide
+ */
+ public void onSliceUnpinned(Uri sliceUri) {
+ }
+
+ /**
* This method must be overridden if an {@link IntentFilter} is specified on the SliceProvider.
* In that case, this method can be called and is expected to return a non-null Uri representing
* a slice. Otherwise this will throw {@link UnsupportedOperationException}.
@@ -221,6 +241,7 @@ public abstract class SliceProvider extends ContentProvider {
getContext().enforceCallingPermission(permission.BIND_SLICE,
"Slice binding requires the permission BIND_SLICE");
Intent intent = extras.getParcelable(EXTRA_INTENT);
+ if (intent == null) return null;
Uri uri = onMapIntentToUri(intent);
List<SliceSpec> supportedSpecs = extras.getParcelableArrayList(EXTRA_SUPPORTED_SPECS);
Bundle b = new Bundle();
@@ -231,10 +252,62 @@ public abstract class SliceProvider extends ContentProvider {
b.putParcelable(EXTRA_SLICE, null);
}
return b;
+ } else if (method.equals(METHOD_PIN)) {
+ Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+ if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) {
+ getContext().enforceUriPermission(uri, permission.BIND_SLICE,
+ permission.BIND_SLICE, Binder.getCallingPid(), Binder.getCallingUid(),
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ "Slice binding requires the permission BIND_SLICE");
+ }
+ handlePinSlice(uri);
+ } else if (method.equals(METHOD_UNPIN)) {
+ Uri uri = extras.getParcelable(EXTRA_BIND_URI);
+ if (!UserHandle.isSameApp(Binder.getCallingUid(), Process.myUid())) {
+ getContext().enforceUriPermission(uri, permission.BIND_SLICE,
+ permission.BIND_SLICE, Binder.getCallingPid(), Binder.getCallingUid(),
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION,
+ "Slice binding requires the permission BIND_SLICE");
+ }
+ handleUnpinSlice(uri);
}
return super.call(method, arg, extras);
}
+ private void handlePinSlice(Uri sliceUri) {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ onSlicePinned(sliceUri);
+ } else {
+ CountDownLatch latch = new CountDownLatch(1);
+ Handler.getMain().post(() -> {
+ onSlicePinned(sliceUri);
+ latch.countDown();
+ });
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private void handleUnpinSlice(Uri sliceUri) {
+ if (Looper.myLooper() == Looper.getMainLooper()) {
+ onSliceUnpinned(sliceUri);
+ } else {
+ CountDownLatch latch = new CountDownLatch(1);
+ Handler.getMain().post(() -> {
+ onSliceUnpinned(sliceUri);
+ latch.countDown();
+ });
+ try {
+ latch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
private Slice handleBindSlice(Uri sliceUri, List<SliceSpec> supportedSpecs) {
if (Looper.myLooper() == Looper.getMainLooper()) {
return onBindSliceStrict(sliceUri, supportedSpecs);
diff --git a/core/java/android/app/slice/SliceSpec.aidl b/core/java/android/app/slice/SliceSpec.aidl
new file mode 100644
index 000000000000..92e98b78a7e8
--- /dev/null
+++ b/core/java/android/app/slice/SliceSpec.aidl
@@ -0,0 +1,19 @@
+/**
+ * Copyright (c) 2017, 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.app.slice;
+
+parcelable SliceSpec;
diff --git a/core/java/android/app/slice/SliceSpec.java b/core/java/android/app/slice/SliceSpec.java
index 433b67e9aacb..8cc0384c1007 100644
--- a/core/java/android/app/slice/SliceSpec.java
+++ b/core/java/android/app/slice/SliceSpec.java
@@ -103,6 +103,11 @@ public final class SliceSpec implements Parcelable {
return mType.equals(other.mType) && mRevision == other.mRevision;
}
+ @Override
+ public String toString() {
+ return String.format("SliceSpec{%s,%d}", mType, mRevision);
+ }
+
public static final Creator<SliceSpec> CREATOR = new Creator<SliceSpec>() {
@Override
public SliceSpec createFromParcel(Parcel source) {