diff options
Diffstat (limited to 'core/java/android')
| -rw-r--r-- | core/java/android/app/slice/ISliceListener.aidl | 25 | ||||
| -rw-r--r-- | core/java/android/app/slice/ISliceManager.aidl | 11 | ||||
| -rw-r--r-- | core/java/android/app/slice/Slice.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/app/slice/SliceManager.java | 92 | ||||
| -rw-r--r-- | core/java/android/app/slice/SliceProvider.java | 73 | ||||
| -rw-r--r-- | core/java/android/app/slice/SliceSpec.aidl | 19 | ||||
| -rw-r--r-- | core/java/android/app/slice/SliceSpec.java | 5 |
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) { |
