WallpaperManagerService.java revision f21adf6fc19bc9c6908c6f1aaae203389f104bfa
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static android.os.FileObserver.*;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static android.os.ParcelFileDescriptor.*;
21111bd4acdb378266221b430a284f88a3990a3958Christopher Tate
228cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.app.IWallpaperManager;
238cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornimport android.app.IWallpaperManagerCallback;
24111bd4acdb378266221b430a284f88a3990a3958Christopher Tateimport android.backup.BackupManager;
254c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.content.ComponentName;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
284c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.content.ServiceConnection;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
304c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.content.pm.ResolveInfo;
314c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.content.pm.ServiceInfo;
329bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport android.content.pm.PackageManager.NameNotFoundException;
339bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport android.content.res.Resources;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
354c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.os.IBinder;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.FileObserver;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteCallbackList;
404c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.os.ServiceManager;
414c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.service.wallpaper.IWallpaperConnection;
424c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.service.wallpaper.IWallpaperEngine;
434c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.service.wallpaper.IWallpaperService;
444c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.service.wallpaper.WallpaperService;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
469bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport android.util.Xml;
474c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.view.IWindowManager;
484c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport android.view.WindowManager;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
509bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport java.io.IOException;
519bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport java.io.InputStream;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileNotFoundException;
549bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport java.io.FileInputStream;
559bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport java.io.FileOutputStream;
564c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackbornimport java.util.List;
579bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
589bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport org.xmlpull.v1.XmlPullParser;
599bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport org.xmlpull.v1.XmlPullParserException;
609bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport org.xmlpull.v1.XmlSerializer;
619bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
62f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackbornimport com.android.internal.service.wallpaper.ImageWallpaper;
639bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onoratoimport com.android.internal.util.FastXmlSerializer;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
658cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackbornclass WallpaperManagerService extends IWallpaperManager.Stub {
664c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    static final String TAG = "WallpaperService";
674c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    static final boolean DEBUG = true;
689bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
694c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    Object mLock = new Object();
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final File WALLPAPER_DIR = new File(
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            "/data/data/com.android.settings/files");
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String WALLPAPER = "wallpaper";
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final File WALLPAPER_FILE = new File(WALLPAPER_DIR, WALLPAPER);
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * List of callbacks registered they should each be notified
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * when the wallpaper is changed.
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
808cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    private final RemoteCallbackList<IWallpaperManagerCallback> mCallbacks
818cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn            = new RemoteCallbackList<IWallpaperManagerCallback>();
829bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * that the wallpaper has changed. The CREATE is triggered when there is no
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * everytime the wallpaper is changed.
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final FileObserver mWallpaperObserver = new FileObserver(
909bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            WALLPAPER_DIR.getAbsolutePath(), CREATE | CLOSE_WRITE | DELETE | DELETE_SELF) {
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                @Override
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                public void onEvent(int event, String path) {
93e712ee3fe1b9ec950dbe5d77993751c2b7b1011cJoe Onorato                    if (path == null) {
94e712ee3fe1b9ec950dbe5d77993751c2b7b1011cJoe Onorato                        return;
95e712ee3fe1b9ec950dbe5d77993751c2b7b1011cJoe Onorato                    }
969bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    synchronized (mLock) {
979bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        // changing the wallpaper means we'll need to back up the new one
989bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        long origId = Binder.clearCallingIdentity();
999bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        BackupManager bm = new BackupManager(mContext);
1009bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        bm.dataChanged();
1019bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        Binder.restoreCallingIdentity(origId);
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        File changedFile = new File(WALLPAPER_DIR, path);
1049bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        if (WALLPAPER_FILE.equals(changedFile)) {
1059bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                            notifyCallbacksLocked();
1069bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        }
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            };
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1114c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    final Context mContext;
1124c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    final IWindowManager mIWindowManager;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1144c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    int mWidth = -1;
1154c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    int mHeight = -1;
1164c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    String mName = "";
1174c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    ComponentName mWallpaperComponent;
1184c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    WallpaperConnection mWallpaperConnection;
1194c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
1204c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    class WallpaperConnection extends IWallpaperConnection.Stub
1214c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            implements ServiceConnection {
1224c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        final Binder mToken = new Binder();
1234c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        IWallpaperService mService;
1244c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        IWallpaperEngine mEngine;
1254c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
1264c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        public void onServiceConnected(ComponentName name, IBinder service) {
1274c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            synchronized (mLock) {
1284c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                if (mWallpaperConnection == this) {
1294c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    mService = IWallpaperService.Stub.asInterface(service);
1304c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    attachServiceLocked(this);
1314c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                }
1324c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            }
1334c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1354c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        public void onServiceDisconnected(ComponentName name) {
1364c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            synchronized (mLock) {
1374c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                mService = null;
1384c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                mEngine = null;
1394c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            }
1404c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
1414c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
1424c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        public void attachEngine(IWallpaperEngine engine) {
1434c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            mEngine = engine;
1444c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
1454c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
1464c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        public ParcelFileDescriptor setWallpaper(String name) {
1474c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            synchronized (mLock) {
1484c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                if (mWallpaperConnection == this) {
1494c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name);
1504c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    if (pfd != null) {
1514c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                        saveSettingsLocked();
1524c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    }
1534c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    return pfd;
1544c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                }
1554c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                return null;
1564c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            }
1574c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
1584c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
1594c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
1608cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    public WallpaperManagerService(Context context) {
1614c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        if (DEBUG) Log.d(TAG, "WallpaperService startup");
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1634c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        mIWindowManager = IWindowManager.Stub.asInterface(
1644c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                ServiceManager.getService(Context.WINDOW_SERVICE));
165e712ee3fe1b9ec950dbe5d77993751c2b7b1011cJoe Onorato        WALLPAPER_DIR.mkdirs();
1669bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        loadSettingsLocked();
167e712ee3fe1b9ec950dbe5d77993751c2b7b1011cJoe Onorato        mWallpaperObserver.startWatching();
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() throws Throwable {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.finalize();
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWallpaperObserver.stopWatching();
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
176f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn    public void systemReady() {
177f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        synchronized (mLock) {
178f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            try {
179f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                bindWallpaperComponentLocked(mWallpaperComponent);
180f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            } catch (RuntimeException e) {
181f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                Log.w(TAG, "Failure starting previous wallpaper", e);
182f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                try {
183f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                    bindWallpaperComponentLocked(null);
184f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                } catch (RuntimeException e2) {
185f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                    Log.w(TAG, "Failure starting default wallpaper", e2);
186f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                    clearWallpaperComponentLocked();
187f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                }
188f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            }
189f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        }
190f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn    }
191f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearWallpaper() {
1939bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        synchronized (mLock) {
1949bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            File f = WALLPAPER_FILE;
1959bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if (f.exists()) {
1969bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                f.delete();
1979bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
198f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            bindWallpaperComponentLocked(null);
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setDimensionHints(int width, int height) throws RemoteException {
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (width <= 0 || height <= 0) {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("width and height must be > 0");
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2099bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        synchronized (mLock) {
2109bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if (width != mWidth || height != mHeight) {
2119bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                mWidth = width;
2129bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                mHeight = height;
2139bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                saveSettingsLocked();
2149bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getWidthHint() throws RemoteException {
2199bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        synchronized (mLock) {
2209bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            return mWidth;
2219bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getHeightHint() throws RemoteException {
2259bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        synchronized (mLock) {
2269bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            return mHeight;
2279bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2308cc6a5026aeb5cf9cc36529426fe0cc66714f5fbDianne Hackborn    public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb) {
2319bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        synchronized (mLock) {
2329bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            try {
2339bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                mCallbacks.register(cb);
2349bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                File f = WALLPAPER_FILE;
2359bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                if (!f.exists()) {
2369bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    return null;
2379bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                }
2389bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
2399bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            } catch (FileNotFoundException e) {
2409bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                /* Shouldn't happen as we check to see if the file exists */
2414c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                Log.w(TAG, "Error getting wallpaper", e);
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2439bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            return null;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2479bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    public ParcelFileDescriptor setWallpaper(String name) {
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        checkPermission(android.Manifest.permission.SET_WALLPAPER);
2499bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        synchronized (mLock) {
2504c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name);
2514c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            if (pfd != null) {
252f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                bindWallpaperComponentLocked(null);
2534c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                saveSettingsLocked();
2544c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            }
2554c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            return pfd;
2564c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
2574c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
2584c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
2594c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    ParcelFileDescriptor updateWallpaperBitmapLocked(String name) {
2604c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        if (name == null) name = "";
2614c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        try {
2624c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            ParcelFileDescriptor fd = ParcelFileDescriptor.open(WALLPAPER_FILE,
2634c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    MODE_CREATE|MODE_READ_WRITE);
2649bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            mName = name;
2654c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            return fd;
2664c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        } catch (FileNotFoundException e) {
2674c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            Log.w(TAG, "Error setting wallpaper", e);
2684c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
2694c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        return null;
2704c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
2714c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
2724c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    public void setWallpaperComponent(ComponentName name) {
2734c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
2744c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        synchronized (mLock) {
2754c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            final long ident = Binder.clearCallingIdentity();
2769bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            try {
277f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                bindWallpaperComponentLocked(name);
278f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            } finally {
279f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                Binder.restoreCallingIdentity(ident);
280f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            }
281f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        }
282f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn    }
283f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn
284f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn    void bindWallpaperComponentLocked(ComponentName name) {
285f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        // Has the component changed?
286f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        if (mWallpaperConnection != null) {
287f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            if (mWallpaperComponent == null) {
288f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                if (name == null) {
289f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                    // Still using default wallpaper.
290f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                    return;
2914c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                }
292f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            } else if (mWallpaperComponent.equals(name)) {
293f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                // Changing to same wallpaper.
294f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                return;
295f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            }
296f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        }
297f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn
298f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        try {
299f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            ComponentName realName = name;
300f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            if (realName == null) {
301f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                // The default component is our static image wallpaper.
302f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                realName = new ComponentName("android",
303f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                        ImageWallpaper.class.getName());
304f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            }
305f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            ServiceInfo si = mContext.getPackageManager().getServiceInfo(realName,
306f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                    PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS);
307f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
308f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                throw new SecurityException("Selected service does not require "
309f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                        + android.Manifest.permission.BIND_WALLPAPER
310f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                        + ": " + realName);
311f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            }
312f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn
313f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
314f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            if (name != null) {
3154c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                // Make sure the selected service is actually a wallpaper service.
3164c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                List<ResolveInfo> ris = mContext.getPackageManager()
3174c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                        .queryIntentServices(intent, 0);
3184c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                for (int i=0; i<ris.size(); i++) {
3194c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    ServiceInfo rsi = ris.get(i).serviceInfo;
3204c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    if (rsi.name.equals(si.name) &&
3214c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                            rsi.packageName.equals(si.packageName)) {
3224c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                        ris = null;
3234c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                        break;
3244c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    }
3254c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                }
3264c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                if (ris != null) {
3274c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    throw new SecurityException("Selected service is not a wallpaper: "
328f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                            + realName);
3294c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                }
3309bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
331f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn
332f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            // Bind the service!
333f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            WallpaperConnection newConn = new WallpaperConnection();
334f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            intent.setComponent(realName);
335f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            if (!mContext.bindService(intent, newConn,
336f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                    Context.BIND_AUTO_CREATE)) {
337f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                throw new IllegalArgumentException("Unable to bind service: "
338f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                        + name);
339f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            }
340f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn
341f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            clearWallpaperComponentLocked();
342f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            mWallpaperComponent = name;
343f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            mWallpaperConnection = newConn;
344f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            try {
345f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                if (DEBUG) Log.v(TAG, "Adding window token: " + newConn.mToken);
346f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                mIWindowManager.addWindowToken(newConn.mToken,
347f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn                        WindowManager.LayoutParams.TYPE_WALLPAPER);
348f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            } catch (RemoteException e) {
349f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            }
350f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn
351f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn        } catch (PackageManager.NameNotFoundException e) {
352f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            throw new IllegalArgumentException("Unknown component " + name);
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3554c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
3564c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    void clearWallpaperComponentLocked() {
3574c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        mWallpaperComponent = null;
3584c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        if (mWallpaperConnection != null) {
3594c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            if (mWallpaperConnection.mEngine != null) {
3604c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                try {
3614c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                    mWallpaperConnection.mEngine.destroy();
3624c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                } catch (RemoteException e) {
3634c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                }
3644c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            }
3654c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            mContext.unbindService(mWallpaperConnection);
3664c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            mWallpaperConnection = null;
3674c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
3684c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
3694c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
3704c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    void attachServiceLocked(WallpaperConnection conn) {
3714c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        try {
3724c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            conn.mService.attach(conn, conn.mToken, mWidth, mHeight);
3734c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        } catch (RemoteException e) {
3744c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            Log.w(TAG, "Failed attaching wallpaper; clearing", e);
375f21adf6fc19bc9c6908c6f1aaae203389f104bfaDianne Hackborn            bindWallpaperComponentLocked(null);
3764c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn        }
3774c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn    }
3784c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn
3799bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    private void notifyCallbacksLocked() {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int n = mCallbacks.beginBroadcast();
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < n; i++) {
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCallbacks.getBroadcastItem(i).onWallpaperChanged();
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // The RemoteCallbackList will take care of removing
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // the dead object for us.
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCallbacks.finishBroadcast();
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.sendBroadcast(intent);
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void checkPermission(String permission) {
3969bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", must have permission " + permission);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4019bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4029bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    private static JournaledFile makeJournaledFile() {
4039bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        final String base = "/data/system/wallpaper_info.xml";
4049bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        return new JournaledFile(new File(base), new File(base + ".tmp"));
4059bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    }
4069bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4079bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    private void saveSettingsLocked() {
4089bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        JournaledFile journal = makeJournaledFile();
4099bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        FileOutputStream stream = null;
4109bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        try {
4119bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            stream = new FileOutputStream(journal.chooseForWrite(), false);
4129bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            XmlSerializer out = new FastXmlSerializer();
4139bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.setOutput(stream, "utf-8");
4149bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.startDocument(null, true);
4159bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4169bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.startTag(null, "wp");
4179bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.attribute(null, "width", Integer.toString(mWidth));
4189bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.attribute(null, "height", Integer.toString(mHeight));
4199bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.attribute(null, "name", mName);
4204c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            if (mWallpaperComponent != null) {
4214c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                out.attribute(null, "component",
4224c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                        mWallpaperComponent.flattenToShortString());
4234c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn            }
4249bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.endTag(null, "wp");
4259bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4269bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            out.endDocument();
4279bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            stream.close();
4289bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            journal.commit();
4299bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        } catch (IOException e) {
4309bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            try {
4319bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                if (stream != null) {
4329bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    stream.close();
4339bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                }
4349bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            } catch (IOException ex) {
4359bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                // Ignore
4369bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
4379bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            journal.rollback();
4389bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
4399bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    }
4409bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4419bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    private void loadSettingsLocked() {
4429bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        JournaledFile journal = makeJournaledFile();
4439bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        FileInputStream stream = null;
4449bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        File file = journal.chooseForRead();
4459bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        boolean success = false;
4469bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        try {
4479bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            stream = new FileInputStream(file);
4489bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            XmlPullParser parser = Xml.newPullParser();
4499bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            parser.setInput(stream, null);
4509bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4519bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            int type;
4529bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            do {
4539bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                type = parser.next();
4549bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                if (type == XmlPullParser.START_TAG) {
4559bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    String tag = parser.getName();
4569bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    if ("wp".equals(tag)) {
4579bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        mWidth = Integer.parseInt(parser.getAttributeValue(null, "width"));
4589bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        mHeight = Integer.parseInt(parser.getAttributeValue(null, "height"));
4599bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        mName = parser.getAttributeValue(null, "name");
4604c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                        String comp = parser.getAttributeValue(null, "component");
4614c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                        mWallpaperComponent = comp != null
4624c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                                ? ComponentName.unflattenFromString(comp)
4634c62fc0e1e5ea9c69a12a7d1cf8b3ec8b2d114a3Dianne Hackborn                                : null;
4649bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    }
4659bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                }
4669bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            } while (type != XmlPullParser.END_DOCUMENT);
4679bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            success = true;
4689bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        } catch (NullPointerException e) {
4692d9c9e3f6780b70fc98cfa0102824308e8ed28e9Joe Onorato            Log.w(TAG, "failed parsing " + file + " " + e);
4709bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        } catch (NumberFormatException e) {
4712d9c9e3f6780b70fc98cfa0102824308e8ed28e9Joe Onorato            Log.w(TAG, "failed parsing " + file + " " + e);
4729bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        } catch (XmlPullParserException e) {
4732d9c9e3f6780b70fc98cfa0102824308e8ed28e9Joe Onorato            Log.w(TAG, "failed parsing " + file + " " + e);
4749bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        } catch (IOException e) {
4752d9c9e3f6780b70fc98cfa0102824308e8ed28e9Joe Onorato            Log.w(TAG, "failed parsing " + file + " " + e);
4769bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        } catch (IndexOutOfBoundsException e) {
4772d9c9e3f6780b70fc98cfa0102824308e8ed28e9Joe Onorato            Log.w(TAG, "failed parsing " + file + " " + e);
4789bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
4799bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        try {
4809bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if (stream != null) {
4819bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                stream.close();
4829bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
4839bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        } catch (IOException e) {
4849bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            // Ignore
4859bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
4869bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4879bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        if (!success) {
4889bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            mWidth = -1;
4899bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            mHeight = -1;
4909bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            mName = "";
4919bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
4929bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    }
4939bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
4949bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    void settingsRestored() {
4959bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        boolean success = false;
4969bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        synchronized (mLock) {
4979bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            loadSettingsLocked();
4989bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            // If there's a wallpaper name, we use that.  If that can't be loaded, then we
4999bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            // use the default.
5009bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if ("".equals(mName)) {
5019bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                success = true;
5029bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            } else {
5039bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                success = restoreNamedResourceLocked();
5049bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
5059bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
5069bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5079bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        if (!success) {
5089bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            Log.e(TAG, "Failed to restore wallpaper: '" + mName + "'");
5099bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            mName = "";
5109bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            WALLPAPER_FILE.delete();
5119bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
5129bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        saveSettingsLocked();
5139bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    }
5149bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5159bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    boolean restoreNamedResourceLocked() {
5169bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        if (mName.length() > 4 && "res:".equals(mName.substring(0, 4))) {
5179bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            String resName = mName.substring(4);
5189bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5199bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            String pkg = null;
5209bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            int colon = resName.indexOf(':');
5219bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if (colon > 0) {
5229bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                pkg = resName.substring(0, colon);
5239bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
5249bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5259bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            String ident = null;
5269bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            int slash = resName.lastIndexOf('/');
5279bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if (slash > 0) {
5289bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                ident = resName.substring(slash+1);
5299bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
5309bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5319bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            String type = null;
5329bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if (colon > 0 && slash > 0 && (slash-colon) > 1) {
5339bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                type = resName.substring(colon+1, slash);
5349bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
5359bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5369bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            if (pkg != null && ident != null && type != null) {
5379bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                int resId = -1;
5389bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                InputStream res = null;
5399bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                FileOutputStream fos = null;
5409bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                try {
5419bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
5429bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    Resources r = c.getResources();
5439bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    resId = r.getIdentifier(resName, null, null);
5449bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    if (resId == 0) {
5459bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        Log.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
5469bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                                + " ident=" + ident);
5479bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        return false;
5489bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    }
5499bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5509bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    res = r.openRawResource(resId);
5519bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    fos = new FileOutputStream(WALLPAPER_FILE);
5529bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5539bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    byte[] buffer = new byte[32768];
5549bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    int amt;
5559bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    while ((amt=res.read(buffer)) > 0) {
5569bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        fos.write(buffer, 0, amt);
5579bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    }
5589bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    // mWallpaperObserver will notice the close and send the change broadcast
5599bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato
5609bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    Log.d(TAG, "Restored wallpaper: " + resName);
5619bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    return true;
5629bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                } catch (NameNotFoundException e) {
5639bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    Log.e(TAG, "Package name " + pkg + " not found");
5649bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                } catch (Resources.NotFoundException e) {
5659bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    Log.e(TAG, "Resource not found: " + resId);
5669bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                } catch (IOException e) {
5679bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    Log.e(TAG, "IOException while restoring wallpaper ", e);
5689bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                } finally {
5699bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    if (res != null) {
5709bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        try {
5719bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                            res.close();
5729bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        } catch (IOException ex) {}
5739bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    }
5749bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    if (fos != null) {
5759bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        try {
5769bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                            fos.close();
5779bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                        } catch (IOException ex) {}
5789bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                    }
5799bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato                }
5809bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato            }
5819bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        }
5829bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato        return false;
5839bb8fd77c8dc177aab9ac96bed4f55972dcda70aJoe Onorato    }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
585