summaryrefslogtreecommitdiffstats
path: root/sdk/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java
diff options
context:
space:
mode:
Diffstat (limited to 'sdk/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java')
-rw-r--r--sdk/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java236
1 files changed, 236 insertions, 0 deletions
diff --git a/sdk/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java b/sdk/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java
new file mode 100644
index 0000000..b15e01a
--- /dev/null
+++ b/sdk/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2015 The CyanogenMod 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 cyanogenmod.externalviews;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+
+import com.android.internal.policy.PhoneWindow;
+
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+
+/**
+ * TODO: unhide once documented and finalized
+ * @hide
+ */
+public abstract class ExternalViewProviderService extends Service {
+
+ private static final String TAG = "ExternalViewProvider";
+ private static final boolean DEBUG = false;
+
+ private WindowManager mWindowManager;
+ private final Handler mHandler = new Handler();
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+ }
+
+ @Override
+ public final IBinder onBind(Intent intent) {
+ return new IExternalViewProviderFactory.Stub() {
+ @Override public IBinder createExternalView(final Bundle options) {
+ FutureTask<IBinder> c = new FutureTask<IBinder>(new Callable<IBinder>() {
+ @Override
+ public IBinder call() throws Exception {
+ return ExternalViewProviderService.this.createExternalView(options).mImpl;
+ }
+ });
+ mHandler.post(c);
+ try {
+ return c.get();
+ } catch (InterruptedException | ExecutionException e) {
+ Log.e(TAG, "error: ", e);
+ return null;
+ }
+ }
+ };
+ }
+
+ protected abstract Provider createExternalView(Bundle options);
+
+ protected abstract class Provider {
+ public static final int DEFAULT_WINDOW_TYPE = WindowManager.LayoutParams.TYPE_PHONE;
+ public static final int DEFAULT_WINDOW_FLAGS =
+ WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
+ WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;;
+
+ private final class ProviderImpl extends IExternalViewProvider.Stub {
+ private final Window mWindow;
+ private final WindowManager.LayoutParams mParams;
+
+ private boolean mShouldShow = true;
+ private boolean mAskedShow = false;
+
+ public ProviderImpl(Provider provider) {
+ mWindow = new PhoneWindow(ExternalViewProviderService.this);
+ ((ViewGroup) mWindow.getDecorView()).addView(onCreateView());
+
+ mParams = new WindowManager.LayoutParams();
+ mParams.type = provider.getWindowType();
+ mParams.flags = provider.getWindowFlags();
+ mParams.gravity = Gravity.LEFT | Gravity.TOP;
+ mParams.format = PixelFormat.TRANSPARENT;
+ }
+
+ @Override
+ public void onAttach(IBinder windowToken) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mWindowManager.addView(mWindow.getDecorView(), mParams);
+ Provider.this.onAttach();
+ }
+ });
+ }
+
+ @Override
+ public void onStart() throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Provider.this.onStart();
+ }
+ });
+ }
+
+ @Override
+ public void onResume() throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mShouldShow = true;
+ updateVisibility();
+ Provider.this.onResume();
+ }
+ });
+ }
+
+ @Override
+ public void onPause() throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mShouldShow = false;
+ updateVisibility();
+ Provider.this.onPause();
+ }
+ });
+ }
+
+ @Override
+ public void onStop() throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ Provider.this.onStop();
+ }
+ });
+ }
+
+ @Override
+ public void onDetach() throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mWindowManager.removeView(mWindow.getDecorView());
+ Provider.this.onDetach();
+ }
+ });
+ }
+
+ @Override
+ public void alterWindow(final int x, final int y, final int width, final int height,
+ final boolean visible, final Rect clipRect) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mParams.x = x;
+ mParams.y = y;
+ mParams.width = width;
+ mParams.height = height;
+
+ if (DEBUG) Log.d(TAG, mParams.toString());
+
+ mAskedShow = visible;
+
+ updateVisibility();
+
+ View decorView = mWindow.getDecorView();
+ if (decorView.getVisibility() == View.VISIBLE) {
+ decorView.setClipBounds(clipRect);
+ }
+
+ if (mWindow.getDecorView().getVisibility() != View.GONE)
+ mWindowManager.updateViewLayout(mWindow.getDecorView(), mParams);
+ }
+ });
+ }
+
+ private void updateVisibility() {
+ if (DEBUG) Log.d(TAG, "shouldShow = " + mShouldShow + " askedShow = " + mAskedShow);
+ mWindow.getDecorView().setVisibility(mShouldShow && mAskedShow ?
+ View.VISIBLE : View.GONE);
+ }
+ }
+
+ private final ProviderImpl mImpl = new ProviderImpl(this);
+ private final Bundle mOptions;
+
+ protected Provider(Bundle options) {
+ mOptions = options;
+ }
+
+ protected Bundle getOptions() {
+ return mOptions;
+ }
+
+ protected void onAttach() {}
+ protected abstract View onCreateView();
+ protected void onStart() {}
+ protected void onResume() {}
+ protected void onPause() {}
+ protected void onStop() {}
+ protected void onDetach() {}
+
+ /*package*/ int getWindowType() {
+ return DEFAULT_WINDOW_TYPE;
+ }
+
+ /*package*/ int getWindowFlags() {
+ return DEFAULT_WINDOW_FLAGS;
+ }
+ }
+} \ No newline at end of file