Implement previews in the wallpaper picker.

Note that the UI is ugly ugly ugly, but previews are actually working.
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 701ca77..6b49b64 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,9 +20,7 @@
 <!--TODO MAKE THE sharedUserId be uid.system again !! -->
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.launcher2"
-    android:sharedUserId="android.uid.system"
-    android:sharedUserLabel="@string/uid_name">
+    package="com.android.launcher2">
 
     <!-- Turned off until there is only one launcher
     <permission
@@ -57,13 +55,16 @@
     <uses-permission android:name="android.permission.READ_CONTACTS"/>
     <uses-permission android:name="android.permission.SET_WALLPAPER" />
     <uses-permission android:name="android.permission.SET_WALLPAPER_HINTS" />
-    <uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT" />
     <uses-permission android:name="android.permission.VIBRATE" />
     <uses-permission android:name="android.permission.WRITE_SETTINGS" />
     <uses-permission android:name="android.permission.BIND_APPWIDGET" />
     <uses-permission android:name="com.android.launcher.permission.READ_SETTINGS" />
     <uses-permission android:name="com.android.launcher.permission.WRITE_SETTINGS" />
 
+    <!-- these two are only needed for the wallpaper picker -->
+    <uses-permission android:name="android.permission.SET_WALLPAPER_COMPONENT" />
+    <uses-permission android:name="android.permission.BIND_WALLPAPER" />
+    
     <!-- During development, run outside acore
         android:process="android.process.acore"
     -->
@@ -97,11 +98,11 @@
             </intent-filter>
         </activity>
 
-        <!-- TODO: MOVE TO SETTINGS -->
+        <!-- TODO: MOVE TO SETTINGS (or actually maybe to its own package) -->
         <!-- Standard picker for live wallpapers -->
         <activity android:name="LiveWallpaperPickActivity"
                 android:label="@string/live_wallpaper_picker_title"
-                android:theme="@*android:style/Theme.Dialog.Alert">
+                android:theme="@android:style/Theme.Wallpaper">
             <intent-filter>
                 <action android:name="android.service.wallpaper.LIVE_WALLPAPER_CHOOSER" />
                 <action android:name="android.intent.action.SET_WALLPAPER" />
diff --git a/res/layout/live_wallpaper_content.xml b/res/layout/live_wallpaper_content.xml
new file mode 100644
index 0000000..68e301e
--- /dev/null
+++ b/res/layout/live_wallpaper_content.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2009 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+
+	<FrameLayout
+	    android:layout_width="fill_parent"
+	    android:layout_height="0px"
+	    android:layout_weight="1"
+	    >
+	
+	    <ListView
+	        android:id="@android:id/list"
+	        android:layout_width="fill_parent"
+	        android:layout_height="fill_parent"
+	        />
+	
+	    <TextView
+	        android:id="@android:id/empty"
+	        android:layout_width="fill_parent"
+	        android:layout_height="fill_parent"
+	        android:gravity="center"
+	        android:text="@string/live_wallpaper_empty"
+	        android:visibility="gone"
+	        android:textAppearance="?android:attr/textAppearanceMedium"
+	        />
+	
+	</FrameLayout>
+	
+    <Button android:id="@+id/set"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/set_live_wallpaper"
+        android:layout_gravity="center_horizontal" />
+	
+</LinearLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 476f47a..75d30e7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -130,4 +130,9 @@
     <!-- Text to show user in place of a gadget when we can't display it properly -->
     <string name="gadget_error_text">Problem loading widget</string>
 
+
+    <!-- STUFF FOR THE WALLPAPER PICKER. -->
+    <string name="live_wallpaper_empty">No live wallpapers.</string>
+    <string name="set_live_wallpaper">Set wallpaper</string>
+    
 </resources>
diff --git a/src/com/android/launcher2/LiveWallpaperPickActivity.java b/src/com/android/launcher2/LiveWallpaperPickActivity.java
index 6119a8a..cfafda0 100644
--- a/src/com/android/launcher2/LiveWallpaperPickActivity.java
+++ b/src/com/android/launcher2/LiveWallpaperPickActivity.java
@@ -16,17 +16,32 @@
 
 package com.android.launcher2;
 
+import android.app.LauncherActivity;
+import android.app.ListActivity;
 import android.app.WallpaperManager;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.graphics.drawable.Drawable;
+import android.os.Binder;
 import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
+import android.os.SystemClock;
+import android.service.wallpaper.IWallpaperConnection;
+import android.service.wallpaper.IWallpaperEngine;
+import android.service.wallpaper.IWallpaperService;
 import android.service.wallpaper.WallpaperService;
 import android.util.Log;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.ListView;
 
 import java.text.Collator;
 import java.util.List;
@@ -38,12 +53,96 @@
  * Displays a list of live wallpapers, allowing the user to select one
  * and make it the system global wallpaper.
  */
-public class LiveWallpaperPickActivity extends ActivityPicker {
+public class LiveWallpaperPickActivity extends LauncherActivity
+        implements View.OnClickListener {
     private static final String TAG = "LiveWallpaperPickActivity";
 
     private PackageManager mPackageManager;
     private WallpaperManager mWallpaperManager;
     
+    Intent mSelectedIntent;
+    WallpaperConnection mWallpaperConnection;
+    
+    class WallpaperConnection extends IWallpaperConnection.Stub
+            implements ServiceConnection {
+        final Intent mIntent;
+        IWallpaperService mService;
+        IWallpaperEngine mEngine;
+        boolean mConnected;
+
+        public WallpaperConnection(Intent intent) {
+            mIntent = intent;
+        }
+        
+        public boolean connect() {
+            synchronized (this) {
+                if (!bindService(mIntent, this, Context.BIND_AUTO_CREATE)) {
+                    return false;
+                }
+                
+                mConnected = true;
+                return true;
+            }
+        }
+        
+        public void disconnect() {
+            synchronized (this) {
+                mConnected = false;
+                if (mEngine != null) {
+                    try {
+                        mEngine.destroy();
+                    } catch (RemoteException e) {
+                    }
+                    mEngine = null;
+                }
+                unbindService(this);
+                mService = null;
+            }
+        }
+        
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            if (mWallpaperConnection == this) {
+                mService = IWallpaperService.Stub.asInterface(service);
+                try {
+                    View button = findViewById(R.id.set);
+                    mService.attach(this, button.getWindowToken(),
+                            WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA,
+                            true,
+                            button.getRootView().getWidth(),
+                            button.getRootView().getHeight());
+                } catch (RemoteException e) {
+                    Log.w(TAG, "Failed attaching wallpaper; clearing", e);
+                }
+            }
+        }
+
+        public void onServiceDisconnected(ComponentName name) {
+            mService = null;
+            mEngine = null;
+            if (mWallpaperConnection == this) {
+                Log.w(TAG, "Wallpaper service gone: " + name);
+            }
+        }
+        
+        public void attachEngine(IWallpaperEngine engine) {
+            synchronized (this) {
+                if (mConnected) {
+                    mEngine = engine;
+                } else {
+                    try {
+                        engine.destroy();
+                    } catch (RemoteException e) {
+                    }
+                }
+            }
+        }
+        
+        public ParcelFileDescriptor setWallpaper(String name) {
+            return null;
+        }
+    }
+    
+    
     @Override
     public void onCreate(Bundle icicle) {
         mPackageManager = getPackageManager();
@@ -51,66 +150,64 @@
         
         super.onCreate(icicle);
         
+        View button = findViewById(R.id.set);
+        button.setEnabled(false);
+        button.setOnClickListener(this);
+        
         // Set default return data
         setResult(RESULT_CANCELED);
     }
     
-    /**
-     * {@inheritDoc}
-     */
     @Override
-    public void onClick(DialogInterface dialog, int which) {
-        Intent intent = getIntentForPosition(which);
-        try {
-            mWallpaperManager.getIWallpaperManager().setWallpaperComponent(
-                    intent.getComponent());
-            this.setResult(RESULT_OK);
-        } catch (RemoteException e) {
-            // do nothing
-        } catch (RuntimeException e) {
-            Log.w(TAG, "Failure setting wallpaper", e);
+    public void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+        if (mWallpaperConnection != null) {
+            mWallpaperConnection.disconnect();
         }
-        finish();
-    }
-
-    void putLiveWallpaperItems(List<ResolveInfo> ris,
-            List<PickAdapter.Item> items) {
-        final int size = ris.size();
-        for (int i = 0; i < size; i++) {
-            ServiceInfo si = ris.get(i).serviceInfo;
-            
-            CharSequence label = si.loadLabel(mPackageManager);
-            Drawable icon = si.loadIcon(mPackageManager);
-            
-            PickAdapter.Item item = new PickAdapter.Item(this, label, icon);
-            
-            item.packageName = si.packageName;
-            item.className = si.name;
-            
-            items.add(item);
-        }
+        mWallpaperConnection = null;
     }
     
     @Override
-    protected List<PickAdapter.Item> getItems() {
-        List<PickAdapter.Item> items = new ArrayList<PickAdapter.Item>();
-        
-        putInstalledLiveWallpapers(items);
-        
-        // Sort all items together by label
-        Collections.sort(items, new Comparator<PickAdapter.Item>() {
-                Collator mCollator = Collator.getInstance();
-                public int compare(PickAdapter.Item lhs, PickAdapter.Item rhs) {
-                    return mCollator.compare(lhs.label, rhs.label);
-                }
-            });
-
-        return items;
+    protected void onSetContentView() {
+        setContentView(R.layout.live_wallpaper_content);
     }
-
-    void putInstalledLiveWallpapers(List<PickAdapter.Item> items) {
-        List<ResolveInfo> ris = mPackageManager.queryIntentServices(
-                new Intent(WallpaperService.SERVICE_INTERFACE), 0);
-        putLiveWallpaperItems(ris, items);
+    
+    @Override
+    protected Intent getTargetIntent() {
+        return new Intent(WallpaperService.SERVICE_INTERFACE);
+    }
+    
+    @Override
+    protected List<ResolveInfo> onQueryPackageManager(Intent queryIntent) {
+        return mPackageManager.queryIntentServices(queryIntent, /* no flags */ 0);
+    }
+    
+    @Override
+    protected void onListItemClick(ListView l, View v, int position, long id) {
+        mSelectedIntent = intentForPosition(position);
+        findViewById(R.id.set).setEnabled(true);
+        
+        WallpaperConnection conn = new WallpaperConnection(mSelectedIntent);
+        if (conn.connect()) {
+            if (mWallpaperConnection != null) {
+                mWallpaperConnection.disconnect();
+            }
+            mWallpaperConnection = conn;
+        }
+    }
+    
+    public void onClick(View v) {
+        if (mSelectedIntent != null) {
+            try {
+                mWallpaperManager.getIWallpaperManager().setWallpaperComponent(
+                        mSelectedIntent.getComponent());
+                this.setResult(RESULT_OK);
+            } catch (RemoteException e) {
+                // do nothing
+            } catch (RuntimeException e) {
+                Log.w(TAG, "Failure setting wallpaper", e);
+            }
+            finish();
+        }
     }
 }