aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--samples/viewhost/.gitignore7
-rw-r--r--samples/viewhost/Android.mk24
-rw-r--r--samples/viewhost/AndroidManifest.xml38
-rw-r--r--samples/viewhost/res/layout/activity_main.xml48
-rw-r--r--samples/viewhost/res/mipmap-hdpi/ic_launcher.pngbin0 -> 3418 bytes
-rw-r--r--samples/viewhost/res/mipmap-mdpi/ic_launcher.pngbin0 -> 2206 bytes
-rw-r--r--samples/viewhost/res/mipmap-xhdpi/ic_launcher.pngbin0 -> 4842 bytes
-rw-r--r--samples/viewhost/res/mipmap-xxhdpi/ic_launcher.pngbin0 -> 7718 bytes
-rw-r--r--samples/viewhost/res/values-v21/styles.xml20
-rw-r--r--samples/viewhost/res/values-w820dp/dimens.xml21
-rw-r--r--samples/viewhost/res/values/dimens.xml20
-rw-r--r--samples/viewhost/res/values/strings.xml21
-rw-r--r--samples/viewhost/res/values/styles.xml23
-rw-r--r--samples/viewhost/src/org/cyanogenmod/samples/extviewhost/MainActivity.java37
-rw-r--r--samples/viewprovider/Android.mk24
-rw-r--r--samples/viewprovider/AndroidManifest.xml34
-rw-r--r--samples/viewprovider/res/drawable-hdpi/ic_launcher.pngbin0 -> 9397 bytes
-rw-r--r--samples/viewprovider/res/drawable-ldpi/ic_launcher.pngbin0 -> 2729 bytes
-rw-r--r--samples/viewprovider/res/drawable-mdpi/ic_launcher.pngbin0 -> 5237 bytes
-rw-r--r--samples/viewprovider/res/drawable-xhdpi/ic_launcher.pngbin0 -> 14383 bytes
-rw-r--r--samples/viewprovider/res/layout/main.xml33
-rw-r--r--samples/viewprovider/res/values/strings.xml20
-rw-r--r--samples/viewprovider/src/org/cyanogenmod/samples/extview/SampleProviderService.java40
-rw-r--r--src/java/cyanogenmod/externalviews/ExternalView.java246
-rw-r--r--src/java/cyanogenmod/externalviews/ExternalViewProperties.java95
-rw-r--r--src/java/cyanogenmod/externalviews/ExternalViewProviderService.java224
-rw-r--r--src/java/cyanogenmod/externalviews/IExternalViewProvider.aidl32
-rw-r--r--src/java/cyanogenmod/externalviews/IExternalViewProviderFactory.aidl25
-rw-r--r--tests/Android.mk2
29 files changed, 1033 insertions, 1 deletions
diff --git a/samples/viewhost/.gitignore b/samples/viewhost/.gitignore
new file mode 100644
index 00000000..9c4de582
--- /dev/null
+++ b/samples/viewhost/.gitignore
@@ -0,0 +1,7 @@
+.gradle
+/local.properties
+/.idea/workspace.xml
+/.idea/libraries
+.DS_Store
+/build
+/captures
diff --git a/samples/viewhost/Android.mk b/samples/viewhost/Android.mk
new file mode 100644
index 00000000..67e82a37
--- /dev/null
+++ b/samples/viewhost/Android.mk
@@ -0,0 +1,24 @@
+# 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.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ org.cyanogenmod.platform.sdk
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src/)
+
+LOCAL_PACKAGE_NAME := CMExternalViewHost
+
+include $(BUILD_PACKAGE)
diff --git a/samples/viewhost/AndroidManifest.xml b/samples/viewhost/AndroidManifest.xml
new file mode 100644
index 00000000..1e30cf05
--- /dev/null
+++ b/samples/viewhost/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.cyanogenmod.samples.extviewhost" >
+
+ <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@mipmap/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
diff --git a/samples/viewhost/res/layout/activity_main.xml b/samples/viewhost/res/layout/activity_main.xml
new file mode 100644
index 00000000..a21a338d
--- /dev/null
+++ b/samples/viewhost/res/layout/activity_main.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin">
+
+ <LinearLayout
+ android:id="@+id/root"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <cyanogenmod.externalviews.ExternalView
+ android:id="@+id/external_view"
+ android:layout_width="match_parent"
+ android:layout_height="200dp"/>
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:background="#FF0000"/>
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:background="#00FF00"/>
+ <View
+ android:layout_width="match_parent"
+ android:layout_height="200dp"
+ android:background="#0000FF"/>
+ </LinearLayout>
+
+</ScrollView> \ No newline at end of file
diff --git a/samples/viewhost/res/mipmap-hdpi/ic_launcher.png b/samples/viewhost/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 00000000..cde69bcc
--- /dev/null
+++ b/samples/viewhost/res/mipmap-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewhost/res/mipmap-mdpi/ic_launcher.png b/samples/viewhost/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 00000000..c133a0cb
--- /dev/null
+++ b/samples/viewhost/res/mipmap-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewhost/res/mipmap-xhdpi/ic_launcher.png b/samples/viewhost/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..bfa42f0e
--- /dev/null
+++ b/samples/viewhost/res/mipmap-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewhost/res/mipmap-xxhdpi/ic_launcher.png b/samples/viewhost/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..324e72cd
--- /dev/null
+++ b/samples/viewhost/res/mipmap-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewhost/res/values-v21/styles.xml b/samples/viewhost/res/values-v21/styles.xml
new file mode 100644
index 00000000..9712f4b5
--- /dev/null
+++ b/samples/viewhost/res/values-v21/styles.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<resources>
+ <style name="AppTheme" parent="android:Theme.Material.Light">
+ </style>
+</resources>
diff --git a/samples/viewhost/res/values-w820dp/dimens.xml b/samples/viewhost/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..4784b6fd
--- /dev/null
+++ b/samples/viewhost/res/values-w820dp/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<resources>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
diff --git a/samples/viewhost/res/values/dimens.xml b/samples/viewhost/res/values/dimens.xml
new file mode 100644
index 00000000..d9dcc26b
--- /dev/null
+++ b/samples/viewhost/res/values/dimens.xml
@@ -0,0 +1,20 @@
+<!--
+ 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.
+-->
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
diff --git a/samples/viewhost/res/values/strings.xml b/samples/viewhost/res/values/strings.xml
new file mode 100644
index 00000000..4762b189
--- /dev/null
+++ b/samples/viewhost/res/values/strings.xml
@@ -0,0 +1,21 @@
+<!--
+ 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.
+-->
+<resources>
+ <string name="app_name">ExternalViewTest</string>
+
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+</resources>
diff --git a/samples/viewhost/res/values/styles.xml b/samples/viewhost/res/values/styles.xml
new file mode 100644
index 00000000..9531e170
--- /dev/null
+++ b/samples/viewhost/res/values/styles.xml
@@ -0,0 +1,23 @@
+<!--
+ 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.
+-->
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ </style>
+
+</resources>
diff --git a/samples/viewhost/src/org/cyanogenmod/samples/extviewhost/MainActivity.java b/samples/viewhost/src/org/cyanogenmod/samples/extviewhost/MainActivity.java
new file mode 100644
index 00000000..0ce662e1
--- /dev/null
+++ b/samples/viewhost/src/org/cyanogenmod/samples/extviewhost/MainActivity.java
@@ -0,0 +1,37 @@
+/*
+ * 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 org.cyanogenmod.samples.extviewhost;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.os.Bundle;
+
+import cyanogenmod.externalviews.ExternalView;
+
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_main);
+ ExternalView ev = (ExternalView) findViewById(R.id.external_view);
+ ComponentName cn = new ComponentName("org.cyanogenmod.samples.extview",
+ "org.cyanogenmod.samples.extview.SampleProviderService");
+ ev.setProviderComponent(cn);
+ }
+
+}
diff --git a/samples/viewprovider/Android.mk b/samples/viewprovider/Android.mk
new file mode 100644
index 00000000..dda3a6f6
--- /dev/null
+++ b/samples/viewprovider/Android.mk
@@ -0,0 +1,24 @@
+# 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.
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+ org.cyanogenmod.platform.sdk
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src/)
+
+LOCAL_PACKAGE_NAME := CMExternalViewProvider
+
+include $(BUILD_PACKAGE) \ No newline at end of file
diff --git a/samples/viewprovider/AndroidManifest.xml b/samples/viewprovider/AndroidManifest.xml
new file mode 100644
index 00000000..0556a03d
--- /dev/null
+++ b/samples/viewprovider/AndroidManifest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.cyanogenmod.samples.extview"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="23" android:targetSdkVersion="23" />
+
+ <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+ <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+ <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+
+ <application android:label="@string/app_name" android:icon="@drawable/ic_launcher">
+ <service android:name=".SampleProviderService"
+ android:exported="true">
+
+ </service>
+ </application>
+</manifest>
diff --git a/samples/viewprovider/res/drawable-hdpi/ic_launcher.png b/samples/viewprovider/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..96a442e5
--- /dev/null
+++ b/samples/viewprovider/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewprovider/res/drawable-ldpi/ic_launcher.png b/samples/viewprovider/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 00000000..99238729
--- /dev/null
+++ b/samples/viewprovider/res/drawable-ldpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewprovider/res/drawable-mdpi/ic_launcher.png b/samples/viewprovider/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..359047df
--- /dev/null
+++ b/samples/viewprovider/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewprovider/res/drawable-xhdpi/ic_launcher.png b/samples/viewprovider/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
--- /dev/null
+++ b/samples/viewprovider/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/samples/viewprovider/res/layout/main.xml b/samples/viewprovider/res/layout/main.xml
new file mode 100644
index 00000000..c2742aaf
--- /dev/null
+++ b/samples/viewprovider/res/layout/main.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:gravity="center_horizontal">
+ <Button
+ android:id="@+id/create_bluetooth_on_wifi_trigger_connect"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/bluetooth_on_wifi_trigger"/>
+
+ <TextView
+ android:id="@+id/create_bt_on_wifi_status"
+ android:layout_width="match_parent"
+ android:layout_height="300dp" />
+</LinearLayout>
+
diff --git a/samples/viewprovider/res/values/strings.xml b/samples/viewprovider/res/values/strings.xml
new file mode 100644
index 00000000..6d6780c6
--- /dev/null
+++ b/samples/viewprovider/res/values/strings.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+<resources>
+ <string name="app_name">Profiles Sample</string>
+ <string name="bluetooth_on_wifi_trigger">Create profile that triggers on top AP from WifiManager</string>
+</resources>
diff --git a/samples/viewprovider/src/org/cyanogenmod/samples/extview/SampleProviderService.java b/samples/viewprovider/src/org/cyanogenmod/samples/extview/SampleProviderService.java
new file mode 100644
index 00000000..21ef2741
--- /dev/null
+++ b/samples/viewprovider/src/org/cyanogenmod/samples/extview/SampleProviderService.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.cyanogenmod.samples.extview;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import cyanogenmod.externalviews.ExternalViewProviderService;
+
+public class SampleProviderService extends ExternalViewProviderService {
+ @Override
+ protected ExternalViewProviderService.Provider createExternalView(Bundle options) {
+ return new ProviderImpl(options);
+ }
+
+ private class ProviderImpl extends Provider {
+ protected ProviderImpl(Bundle options) {
+ super(options);
+ }
+
+ @Override
+ protected View onCreateView() {
+ return LayoutInflater.from(SampleProviderService.this).inflate(R.layout.main, null);
+ }
+ }
+}
diff --git a/src/java/cyanogenmod/externalviews/ExternalView.java b/src/java/cyanogenmod/externalviews/ExternalView.java
new file mode 100644
index 00000000..a593af3f
--- /dev/null
+++ b/src/java/cyanogenmod/externalviews/ExternalView.java
@@ -0,0 +1,246 @@
+/*
+ * 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.Activity;
+import android.app.Application;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import java.util.LinkedList;
+
+/**
+ * TODO: unhide once documented and finalized
+ * @hide
+ */
+public class ExternalView extends View implements Application.ActivityLifecycleCallbacks,
+ ViewTreeObserver.OnPreDrawListener {
+
+ private Context mContext;
+ private LinkedList<Runnable> mQueue = new LinkedList<Runnable>();
+ private volatile IExternalViewProvider mExternalViewProvider;
+ private final ExternalViewProperties mExternalViewProperties;
+
+ public ExternalView(Context context, AttributeSet attrs) {
+ this(context, attrs, null);
+ }
+
+ public ExternalView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs);
+ }
+
+ public ExternalView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+ this(context, attrs);
+ }
+
+ public ExternalView(Context context, AttributeSet attributeSet, ComponentName componentName) {
+ super(context, attributeSet);
+ mContext = getContext();
+ mExternalViewProperties = new ExternalViewProperties(this, mContext);
+ Application app = (mContext instanceof Activity) ? ((Activity) mContext).getApplication()
+ : (Application) mContext;
+ app.registerActivityLifecycleCallbacks(this);
+ if (componentName != null) {
+ mContext.bindService(new Intent().setComponent(componentName),
+ mServiceConnection, Context.BIND_AUTO_CREATE);
+ }
+ }
+
+ private ServiceConnection mServiceConnection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ try {
+ mExternalViewProvider = IExternalViewProvider.Stub.asInterface(
+ IExternalViewProviderFactory.Stub.asInterface(service).createExternalView(null));
+ executeQueue();
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ mExternalViewProvider = null;
+ }
+ };
+
+ private void executeQueue() {
+ while (!mQueue.isEmpty()) {
+ Runnable r = mQueue.pop();
+ r.run();
+ }
+ }
+
+ private void performAction(Runnable r) {
+ if (mExternalViewProvider != null) {
+ r.run();
+ } else {
+ mQueue.add(r);
+ }
+ }
+
+ // view overrides, for positioning
+
+ @Override
+ public boolean onPreDraw() {
+ long cur = System.currentTimeMillis();
+ if (!mExternalViewProperties.hasChanged()) {
+ return true;
+ }
+ final int x = mExternalViewProperties.getX();
+ final int y = mExternalViewProperties.getY();
+ final int width = mExternalViewProperties.getWidth();
+ final int height = mExternalViewProperties.getHeight();
+ final boolean visible = mExternalViewProperties.isVisible();
+ final Rect clipRect = mExternalViewProperties.getHitRect();
+ performAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mExternalViewProvider.alterWindow(x, y, width, height, visible,
+ clipRect);
+ } catch (RemoteException e) {
+ }
+ }
+ });
+ return true;
+ }
+
+ // Activity lifecycle callbacks
+
+ @Override
+ public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
+ }
+
+ @Override
+ public void onActivityStarted(Activity activity) {
+ performAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mExternalViewProvider.onStart();
+ } catch (RemoteException e) {
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onActivityResumed(Activity activity) {
+ performAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mExternalViewProvider.onResume();
+ } catch (RemoteException e) {
+ }
+ getViewTreeObserver().addOnPreDrawListener(ExternalView.this);
+ }
+ });
+ }
+
+ @Override
+ public void onActivityPaused(Activity activity) {
+ performAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mExternalViewProvider.onPause();
+ } catch (RemoteException e) {
+ }
+ getViewTreeObserver().removeOnPreDrawListener(ExternalView.this);
+ }
+ });
+ }
+
+ @Override
+ public void onActivityStopped(Activity activity) {
+ performAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mExternalViewProvider.onStop();
+ } catch (RemoteException e) {
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+ }
+
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ mExternalViewProvider = null;
+ mContext.unbindService(mServiceConnection);
+ }
+
+ // Placeholder callbacks
+
+ @Override
+ public void onDetachedFromWindow() {
+ performAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mExternalViewProvider.onDetach();
+ } catch (RemoteException e) {
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ performAction(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mExternalViewProvider.onAttach(null);
+ } catch (RemoteException e) {
+ }
+ }
+ });
+ }
+
+ /**
+ * Sets the component of the ExternalViewProviderService to be used for this ExternalView.
+ * If a provider is already connected to this view, it is first unbound before binding to the
+ * new provider.
+ * @param componentName
+ */
+ public void setProviderComponent(ComponentName componentName) {
+ // unbind any existing external view provider
+ if (mExternalViewProvider != null) {
+ mContext.unbindService(mServiceConnection);
+ }
+ if (componentName != null) {
+ mContext.bindService(new Intent().setComponent(componentName),
+ mServiceConnection, Context.BIND_AUTO_CREATE);
+ }
+ }
+}
diff --git a/src/java/cyanogenmod/externalviews/ExternalViewProperties.java b/src/java/cyanogenmod/externalviews/ExternalViewProperties.java
new file mode 100644
index 00000000..2b4404d9
--- /dev/null
+++ b/src/java/cyanogenmod/externalviews/ExternalViewProperties.java
@@ -0,0 +1,95 @@
+/*
+ * 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.Activity;
+import android.app.Application;
+import android.content.Context;
+import android.graphics.Rect;
+import android.view.View;
+
+/**
+ * TODO: unhide once documented and finalized
+ * @hide
+ */
+public class ExternalViewProperties {
+
+ private final int[] mScreenCoords = new int[2];
+ private final View mView;
+ private final View mDecorView;
+ private int mWidth, mHeight;
+ private boolean mVisible;
+ private Rect mHitRect = new Rect();
+
+ ExternalViewProperties(View view, Context context) {
+ mView = view;
+ if (context instanceof Activity) {
+ mDecorView = ((Activity) context).getWindow().getDecorView();
+ } else {
+ mDecorView = null;
+ }
+ }
+
+ public Rect getHitRect() {
+ return mHitRect;
+ }
+
+ public int getX() {
+ return mScreenCoords[0];
+ }
+
+ public int getY() {
+ return mScreenCoords[1];
+ }
+
+ public int getWidth() {
+ return mWidth;
+ }
+
+ public int getHeight() {
+ return mHeight;
+ }
+
+ public boolean isVisible() {
+ return mVisible;
+ }
+
+ public boolean hasChanged() {
+ int previousWidth = mWidth;
+ int previousHeight = mHeight;
+ mWidth = mView.getWidth();
+ mHeight = mView.getHeight();
+
+ int previousX = mScreenCoords[0];
+ int previousY = mScreenCoords[1];
+ mView.getLocationOnScreen(mScreenCoords);
+ int newX = mScreenCoords[0];
+ int newY = mScreenCoords[1];
+
+ mHitRect.setEmpty();
+ if (mDecorView != null) {
+ mDecorView.getHitRect(mHitRect);
+ }
+ boolean visible = mView.getLocalVisibleRect(mHitRect);
+ mVisible = visible;
+
+ // Check if anything actually changed
+ return previousX != newX || previousY != newY
+ || previousWidth != mWidth || previousHeight != mHeight
+ || mVisible != visible;
+ }
+}
diff --git a/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java b/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java
new file mode 100644
index 00000000..45230022
--- /dev/null
+++ b/src/java/cyanogenmod/externalviews/ExternalViewProviderService.java
@@ -0,0 +1,224 @@
+/*
+ * 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 {
+ 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() {
+ mWindow = new PhoneWindow(ExternalViewProviderService.this);
+ ((ViewGroup) mWindow.getDecorView()).addView(onCreateView());
+
+ mParams = new WindowManager.LayoutParams();
+ mParams.type = WindowManager.LayoutParams.TYPE_PHONE;
+ mParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
+ WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ 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();
+ 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() {}
+ }
+}
diff --git a/src/java/cyanogenmod/externalviews/IExternalViewProvider.aidl b/src/java/cyanogenmod/externalviews/IExternalViewProvider.aidl
new file mode 100644
index 00000000..e05215f0
--- /dev/null
+++ b/src/java/cyanogenmod/externalviews/IExternalViewProvider.aidl
@@ -0,0 +1,32 @@
+/**
+ * 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.graphics.Rect;
+
+/** @hide */
+interface IExternalViewProvider
+{
+ oneway void onAttach(in IBinder windowToken);
+ oneway void onStart();
+ oneway void onResume();
+ oneway void onPause();
+ oneway void onStop();
+ oneway void onDetach();
+
+ void alterWindow(in int x, in int y, in int width, in int height, in boolean visible, in Rect clipRect);
+}
diff --git a/src/java/cyanogenmod/externalviews/IExternalViewProviderFactory.aidl b/src/java/cyanogenmod/externalviews/IExternalViewProviderFactory.aidl
new file mode 100644
index 00000000..75a8b353
--- /dev/null
+++ b/src/java/cyanogenmod/externalviews/IExternalViewProviderFactory.aidl
@@ -0,0 +1,25 @@
+/**
+ * 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.os.Bundle;
+
+/** @hide */
+interface IExternalViewProviderFactory
+{
+ IBinder createExternalView(in Bundle options);
+}
diff --git a/tests/Android.mk b/tests/Android.mk
index d60a11df..e8a73835 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -21,7 +21,7 @@ LOCAL_MODULE_TAGS := tests
LOCAL_STATIC_JAVA_LIBRARIES := \
org.cyanogenmod.platform.sdk
-LOCAL_SRC_FILES := $(call all-subdir-java-files)
+LOCAL_SRC_FILES := $(call all-subdir-java-files, src/)
LOCAL_PACKAGE_NAME := CMPlatformTests
LOCAL_CERTIFICATE := platform