PageRenderTime 50ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/services/java/com/android/server/WallpaperManagerService.java

https://github.com/aizuzi/platform_frameworks_base
Java | 1345 lines | 1145 code | 106 blank | 94 comment | 260 complexity | 2a2875d2135aec24947a9d7ecfc88417 MD5 | raw file
  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.android.server;
  17. import static android.os.ParcelFileDescriptor.*;
  18. import android.app.ActivityManagerNative;
  19. import android.app.AppGlobals;
  20. import android.app.IUserSwitchObserver;
  21. import android.app.IWallpaperManager;
  22. import android.app.IWallpaperManagerCallback;
  23. import android.app.PendingIntent;
  24. import android.app.WallpaperInfo;
  25. import android.app.backup.BackupManager;
  26. import android.app.backup.WallpaperBackupHelper;
  27. import android.content.BroadcastReceiver;
  28. import android.content.ComponentName;
  29. import android.content.Context;
  30. import android.content.Intent;
  31. import android.content.IntentFilter;
  32. import android.content.ServiceConnection;
  33. import android.content.pm.IPackageManager;
  34. import android.content.pm.PackageManager;
  35. import android.content.pm.ResolveInfo;
  36. import android.content.pm.ServiceInfo;
  37. import android.content.pm.PackageManager.NameNotFoundException;
  38. import android.content.pm.UserInfo;
  39. import android.content.res.Resources;
  40. import android.graphics.Point;
  41. import android.os.Binder;
  42. import android.os.Bundle;
  43. import android.os.Environment;
  44. import android.os.FileUtils;
  45. import android.os.IBinder;
  46. import android.os.IRemoteCallback;
  47. import android.os.RemoteException;
  48. import android.os.FileObserver;
  49. import android.os.ParcelFileDescriptor;
  50. import android.os.RemoteCallbackList;
  51. import android.os.SELinux;
  52. import android.os.ServiceManager;
  53. import android.os.SystemClock;
  54. import android.os.UserHandle;
  55. import android.os.UserManager;
  56. import android.service.wallpaper.IWallpaperConnection;
  57. import android.service.wallpaper.IWallpaperEngine;
  58. import android.service.wallpaper.IWallpaperService;
  59. import android.service.wallpaper.WallpaperService;
  60. import android.util.Slog;
  61. import android.util.SparseArray;
  62. import android.util.Xml;
  63. import android.view.Display;
  64. import android.view.IWindowManager;
  65. import android.view.WindowManager;
  66. import java.io.FileDescriptor;
  67. import java.io.IOException;
  68. import java.io.InputStream;
  69. import java.io.File;
  70. import java.io.FileNotFoundException;
  71. import java.io.FileInputStream;
  72. import java.io.FileOutputStream;
  73. import java.io.PrintWriter;
  74. import java.util.List;
  75. import org.xmlpull.v1.XmlPullParser;
  76. import org.xmlpull.v1.XmlPullParserException;
  77. import org.xmlpull.v1.XmlSerializer;
  78. import com.android.internal.content.PackageMonitor;
  79. import com.android.internal.util.FastXmlSerializer;
  80. import com.android.internal.util.JournaledFile;
  81. class WallpaperManagerService extends IWallpaperManager.Stub {
  82. static final String TAG = "WallpaperService";
  83. static final boolean DEBUG = false;
  84. final Object mLock = new Object[0];
  85. /**
  86. * Minimum time between crashes of a wallpaper service for us to consider
  87. * restarting it vs. just reverting to the static wallpaper.
  88. */
  89. static final long MIN_WALLPAPER_CRASH_TIME = 10000;
  90. static final String WALLPAPER = "wallpaper";
  91. static final String WALLPAPER_INFO = "wallpaper_info.xml";
  92. /**
  93. * Name of the component used to display bitmap wallpapers from either the gallery or
  94. * built-in wallpapers.
  95. */
  96. static final ComponentName IMAGE_WALLPAPER = new ComponentName("com.android.systemui",
  97. "com.android.systemui.ImageWallpaper");
  98. /**
  99. * Observes the wallpaper for changes and notifies all IWallpaperServiceCallbacks
  100. * that the wallpaper has changed. The CREATE is triggered when there is no
  101. * wallpaper set and is created for the first time. The CLOSE_WRITE is triggered
  102. * everytime the wallpaper is changed.
  103. */
  104. private class WallpaperObserver extends FileObserver {
  105. final WallpaperData mWallpaper;
  106. final File mWallpaperDir;
  107. final File mWallpaperFile;
  108. public WallpaperObserver(WallpaperData wallpaper) {
  109. super(getWallpaperDir(wallpaper.userId).getAbsolutePath(),
  110. CLOSE_WRITE | DELETE | DELETE_SELF);
  111. mWallpaperDir = getWallpaperDir(wallpaper.userId);
  112. mWallpaper = wallpaper;
  113. mWallpaperFile = new File(mWallpaperDir, WALLPAPER);
  114. }
  115. @Override
  116. public void onEvent(int event, String path) {
  117. if (path == null) {
  118. return;
  119. }
  120. synchronized (mLock) {
  121. // changing the wallpaper means we'll need to back up the new one
  122. long origId = Binder.clearCallingIdentity();
  123. BackupManager bm = new BackupManager(mContext);
  124. bm.dataChanged();
  125. Binder.restoreCallingIdentity(origId);
  126. File changedFile = new File(mWallpaperDir, path);
  127. if (mWallpaperFile.equals(changedFile)) {
  128. notifyCallbacksLocked(mWallpaper);
  129. if (mWallpaper.wallpaperComponent == null || event != CLOSE_WRITE
  130. || mWallpaper.imageWallpaperPending) {
  131. if (event == CLOSE_WRITE) {
  132. mWallpaper.imageWallpaperPending = false;
  133. }
  134. bindWallpaperComponentLocked(IMAGE_WALLPAPER, true,
  135. false, mWallpaper, null);
  136. saveSettingsLocked(mWallpaper);
  137. }
  138. }
  139. }
  140. }
  141. }
  142. final Context mContext;
  143. final IWindowManager mIWindowManager;
  144. final IPackageManager mIPackageManager;
  145. final MyPackageMonitor mMonitor;
  146. WallpaperData mLastWallpaper;
  147. SparseArray<WallpaperData> mWallpaperMap = new SparseArray<WallpaperData>();
  148. int mCurrentUserId;
  149. static class WallpaperData {
  150. int userId;
  151. File wallpaperFile;
  152. /**
  153. * Client is currently writing a new image wallpaper.
  154. */
  155. boolean imageWallpaperPending;
  156. /**
  157. * Resource name if using a picture from the wallpaper gallery
  158. */
  159. String name = "";
  160. /**
  161. * The component name of the currently set live wallpaper.
  162. */
  163. ComponentName wallpaperComponent;
  164. /**
  165. * The component name of the wallpaper that should be set next.
  166. */
  167. ComponentName nextWallpaperComponent;
  168. WallpaperConnection connection;
  169. long lastDiedTime;
  170. boolean wallpaperUpdating;
  171. WallpaperObserver wallpaperObserver;
  172. /**
  173. * List of callbacks registered they should each be notified when the wallpaper is changed.
  174. */
  175. private RemoteCallbackList<IWallpaperManagerCallback> callbacks
  176. = new RemoteCallbackList<IWallpaperManagerCallback>();
  177. int width = -1;
  178. int height = -1;
  179. WallpaperData(int userId) {
  180. this.userId = userId;
  181. wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
  182. }
  183. }
  184. class WallpaperConnection extends IWallpaperConnection.Stub
  185. implements ServiceConnection {
  186. final WallpaperInfo mInfo;
  187. final Binder mToken = new Binder();
  188. IWallpaperService mService;
  189. IWallpaperEngine mEngine;
  190. WallpaperData mWallpaper;
  191. IRemoteCallback mReply;
  192. boolean mDimensionsChanged = false;
  193. public WallpaperConnection(WallpaperInfo info, WallpaperData wallpaper) {
  194. mInfo = info;
  195. mWallpaper = wallpaper;
  196. }
  197. @Override
  198. public void onServiceConnected(ComponentName name, IBinder service) {
  199. synchronized (mLock) {
  200. if (mWallpaper.connection == this) {
  201. mWallpaper.lastDiedTime = SystemClock.uptimeMillis();
  202. mService = IWallpaperService.Stub.asInterface(service);
  203. attachServiceLocked(this, mWallpaper);
  204. // XXX should probably do saveSettingsLocked() later
  205. // when we have an engine, but I'm not sure about
  206. // locking there and anyway we always need to be able to
  207. // recover if there is something wrong.
  208. saveSettingsLocked(mWallpaper);
  209. }
  210. }
  211. }
  212. @Override
  213. public void onServiceDisconnected(ComponentName name) {
  214. synchronized (mLock) {
  215. mService = null;
  216. mEngine = null;
  217. if (mWallpaper.connection == this) {
  218. Slog.w(TAG, "Wallpaper service gone: " + mWallpaper.wallpaperComponent);
  219. if (!mWallpaper.wallpaperUpdating
  220. && (mWallpaper.lastDiedTime + MIN_WALLPAPER_CRASH_TIME)
  221. > SystemClock.uptimeMillis()
  222. && mWallpaper.userId == mCurrentUserId) {
  223. Slog.w(TAG, "Reverting to built-in wallpaper!");
  224. clearWallpaperLocked(true, mWallpaper.userId, null);
  225. }
  226. }
  227. }
  228. }
  229. @Override
  230. public void attachEngine(IWallpaperEngine engine) {
  231. synchronized (mLock) {
  232. mEngine = engine;
  233. if (mDimensionsChanged) {
  234. try {
  235. mEngine.setDesiredSize(mWallpaper.width, mWallpaper.height);
  236. } catch (RemoteException e) {
  237. Slog.w(TAG, "Failed to set wallpaper dimensions", e);
  238. }
  239. mDimensionsChanged = false;
  240. }
  241. }
  242. }
  243. @Override
  244. public void engineShown(IWallpaperEngine engine) {
  245. synchronized (mLock) {
  246. if (mReply != null) {
  247. long ident = Binder.clearCallingIdentity();
  248. try {
  249. mReply.sendResult(null);
  250. } catch (RemoteException e) {
  251. Binder.restoreCallingIdentity(ident);
  252. }
  253. mReply = null;
  254. }
  255. }
  256. }
  257. @Override
  258. public ParcelFileDescriptor setWallpaper(String name) {
  259. synchronized (mLock) {
  260. if (mWallpaper.connection == this) {
  261. return updateWallpaperBitmapLocked(name, mWallpaper);
  262. }
  263. return null;
  264. }
  265. }
  266. }
  267. class MyPackageMonitor extends PackageMonitor {
  268. @Override
  269. public void onPackageUpdateFinished(String packageName, int uid) {
  270. synchronized (mLock) {
  271. if (mCurrentUserId != getChangingUserId()) {
  272. return;
  273. }
  274. WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
  275. if (wallpaper != null) {
  276. if (wallpaper.wallpaperComponent != null
  277. && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
  278. wallpaper.wallpaperUpdating = false;
  279. ComponentName comp = wallpaper.wallpaperComponent;
  280. clearWallpaperComponentLocked(wallpaper);
  281. if (!bindWallpaperComponentLocked(comp, false, false,
  282. wallpaper, null)) {
  283. Slog.w(TAG, "Wallpaper no longer available; reverting to default");
  284. clearWallpaperLocked(false, wallpaper.userId, null);
  285. }
  286. }
  287. }
  288. }
  289. }
  290. @Override
  291. public void onPackageModified(String packageName) {
  292. synchronized (mLock) {
  293. if (mCurrentUserId != getChangingUserId()) {
  294. return;
  295. }
  296. WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
  297. if (wallpaper != null) {
  298. if (wallpaper.wallpaperComponent == null
  299. || !wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
  300. return;
  301. }
  302. doPackagesChangedLocked(true, wallpaper);
  303. }
  304. }
  305. }
  306. @Override
  307. public void onPackageUpdateStarted(String packageName, int uid) {
  308. synchronized (mLock) {
  309. if (mCurrentUserId != getChangingUserId()) {
  310. return;
  311. }
  312. WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
  313. if (wallpaper != null) {
  314. if (wallpaper.wallpaperComponent != null
  315. && wallpaper.wallpaperComponent.getPackageName().equals(packageName)) {
  316. wallpaper.wallpaperUpdating = true;
  317. }
  318. }
  319. }
  320. }
  321. @Override
  322. public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
  323. synchronized (mLock) {
  324. boolean changed = false;
  325. if (mCurrentUserId != getChangingUserId()) {
  326. return false;
  327. }
  328. WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
  329. if (wallpaper != null) {
  330. boolean res = doPackagesChangedLocked(doit, wallpaper);
  331. changed |= res;
  332. }
  333. return changed;
  334. }
  335. }
  336. @Override
  337. public void onSomePackagesChanged() {
  338. synchronized (mLock) {
  339. if (mCurrentUserId != getChangingUserId()) {
  340. return;
  341. }
  342. WallpaperData wallpaper = mWallpaperMap.get(mCurrentUserId);
  343. if (wallpaper != null) {
  344. doPackagesChangedLocked(true, wallpaper);
  345. }
  346. }
  347. }
  348. boolean doPackagesChangedLocked(boolean doit, WallpaperData wallpaper) {
  349. boolean changed = false;
  350. if (wallpaper.wallpaperComponent != null) {
  351. int change = isPackageDisappearing(wallpaper.wallpaperComponent
  352. .getPackageName());
  353. if (change == PACKAGE_PERMANENT_CHANGE
  354. || change == PACKAGE_TEMPORARY_CHANGE) {
  355. changed = true;
  356. if (doit) {
  357. Slog.w(TAG, "Wallpaper uninstalled, removing: "
  358. + wallpaper.wallpaperComponent);
  359. clearWallpaperLocked(false, wallpaper.userId, null);
  360. }
  361. }
  362. }
  363. if (wallpaper.nextWallpaperComponent != null) {
  364. int change = isPackageDisappearing(wallpaper.nextWallpaperComponent
  365. .getPackageName());
  366. if (change == PACKAGE_PERMANENT_CHANGE
  367. || change == PACKAGE_TEMPORARY_CHANGE) {
  368. wallpaper.nextWallpaperComponent = null;
  369. }
  370. }
  371. if (wallpaper.wallpaperComponent != null
  372. && isPackageModified(wallpaper.wallpaperComponent.getPackageName())) {
  373. try {
  374. mContext.getPackageManager().getServiceInfo(
  375. wallpaper.wallpaperComponent, 0);
  376. } catch (NameNotFoundException e) {
  377. Slog.w(TAG, "Wallpaper component gone, removing: "
  378. + wallpaper.wallpaperComponent);
  379. clearWallpaperLocked(false, wallpaper.userId, null);
  380. }
  381. }
  382. if (wallpaper.nextWallpaperComponent != null
  383. && isPackageModified(wallpaper.nextWallpaperComponent.getPackageName())) {
  384. try {
  385. mContext.getPackageManager().getServiceInfo(
  386. wallpaper.nextWallpaperComponent, 0);
  387. } catch (NameNotFoundException e) {
  388. wallpaper.nextWallpaperComponent = null;
  389. }
  390. }
  391. return changed;
  392. }
  393. }
  394. public WallpaperManagerService(Context context) {
  395. if (DEBUG) Slog.v(TAG, "WallpaperService startup");
  396. mContext = context;
  397. mIWindowManager = IWindowManager.Stub.asInterface(
  398. ServiceManager.getService(Context.WINDOW_SERVICE));
  399. mIPackageManager = AppGlobals.getPackageManager();
  400. mMonitor = new MyPackageMonitor();
  401. mMonitor.register(context, null, UserHandle.ALL, true);
  402. getWallpaperDir(UserHandle.USER_OWNER).mkdirs();
  403. loadSettingsLocked(UserHandle.USER_OWNER);
  404. }
  405. private static File getWallpaperDir(int userId) {
  406. return Environment.getUserSystemDirectory(userId);
  407. }
  408. @Override
  409. protected void finalize() throws Throwable {
  410. super.finalize();
  411. for (int i = 0; i < mWallpaperMap.size(); i++) {
  412. WallpaperData wallpaper = mWallpaperMap.valueAt(i);
  413. wallpaper.wallpaperObserver.stopWatching();
  414. }
  415. }
  416. public void systemRunning() {
  417. if (DEBUG) Slog.v(TAG, "systemReady");
  418. WallpaperData wallpaper = mWallpaperMap.get(UserHandle.USER_OWNER);
  419. switchWallpaper(wallpaper, null);
  420. wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
  421. wallpaper.wallpaperObserver.startWatching();
  422. IntentFilter userFilter = new IntentFilter();
  423. userFilter.addAction(Intent.ACTION_USER_REMOVED);
  424. userFilter.addAction(Intent.ACTION_USER_STOPPING);
  425. mContext.registerReceiver(new BroadcastReceiver() {
  426. @Override
  427. public void onReceive(Context context, Intent intent) {
  428. String action = intent.getAction();
  429. if (Intent.ACTION_USER_REMOVED.equals(action)) {
  430. onRemoveUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
  431. UserHandle.USER_NULL));
  432. }
  433. // TODO: Race condition causing problems when cleaning up on stopping a user.
  434. // Comment this out for now.
  435. // else if (Intent.ACTION_USER_STOPPING.equals(action)) {
  436. // onStoppingUser(intent.getIntExtra(Intent.EXTRA_USER_HANDLE,
  437. // UserHandle.USER_NULL));
  438. // }
  439. }
  440. }, userFilter);
  441. try {
  442. ActivityManagerNative.getDefault().registerUserSwitchObserver(
  443. new IUserSwitchObserver.Stub() {
  444. @Override
  445. public void onUserSwitching(int newUserId, IRemoteCallback reply) {
  446. switchUser(newUserId, reply);
  447. }
  448. @Override
  449. public void onUserSwitchComplete(int newUserId) throws RemoteException {
  450. }
  451. });
  452. } catch (RemoteException e) {
  453. // TODO Auto-generated catch block
  454. e.printStackTrace();
  455. }
  456. }
  457. String getName() {
  458. synchronized (mLock) {
  459. return mWallpaperMap.get(0).name;
  460. }
  461. }
  462. void onStoppingUser(int userId) {
  463. if (userId < 1) return;
  464. synchronized (mLock) {
  465. WallpaperData wallpaper = mWallpaperMap.get(userId);
  466. if (wallpaper != null) {
  467. if (wallpaper.wallpaperObserver != null) {
  468. wallpaper.wallpaperObserver.stopWatching();
  469. wallpaper.wallpaperObserver = null;
  470. }
  471. mWallpaperMap.remove(userId);
  472. }
  473. }
  474. }
  475. void onRemoveUser(int userId) {
  476. if (userId < 1) return;
  477. synchronized (mLock) {
  478. onStoppingUser(userId);
  479. File wallpaperFile = new File(getWallpaperDir(userId), WALLPAPER);
  480. wallpaperFile.delete();
  481. File wallpaperInfoFile = new File(getWallpaperDir(userId), WALLPAPER_INFO);
  482. wallpaperInfoFile.delete();
  483. }
  484. }
  485. void switchUser(int userId, IRemoteCallback reply) {
  486. synchronized (mLock) {
  487. mCurrentUserId = userId;
  488. WallpaperData wallpaper = mWallpaperMap.get(userId);
  489. if (wallpaper == null) {
  490. wallpaper = new WallpaperData(userId);
  491. mWallpaperMap.put(userId, wallpaper);
  492. loadSettingsLocked(userId);
  493. }
  494. // Not started watching yet, in case wallpaper data was loaded for other reasons.
  495. if (wallpaper.wallpaperObserver == null) {
  496. wallpaper.wallpaperObserver = new WallpaperObserver(wallpaper);
  497. wallpaper.wallpaperObserver.startWatching();
  498. }
  499. switchWallpaper(wallpaper, reply);
  500. }
  501. }
  502. void switchWallpaper(WallpaperData wallpaper, IRemoteCallback reply) {
  503. synchronized (mLock) {
  504. RuntimeException e = null;
  505. try {
  506. ComponentName cname = wallpaper.wallpaperComponent != null ?
  507. wallpaper.wallpaperComponent : wallpaper.nextWallpaperComponent;
  508. if (bindWallpaperComponentLocked(cname, true, false, wallpaper, reply)) {
  509. return;
  510. }
  511. } catch (RuntimeException e1) {
  512. e = e1;
  513. }
  514. Slog.w(TAG, "Failure starting previous wallpaper", e);
  515. clearWallpaperLocked(false, wallpaper.userId, reply);
  516. }
  517. }
  518. public void clearWallpaper() {
  519. if (DEBUG) Slog.v(TAG, "clearWallpaper");
  520. synchronized (mLock) {
  521. clearWallpaperLocked(false, UserHandle.getCallingUserId(), null);
  522. }
  523. }
  524. void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) {
  525. WallpaperData wallpaper = mWallpaperMap.get(userId);
  526. File f = new File(getWallpaperDir(userId), WALLPAPER);
  527. if (f.exists()) {
  528. f.delete();
  529. }
  530. final long ident = Binder.clearCallingIdentity();
  531. RuntimeException e = null;
  532. try {
  533. wallpaper.imageWallpaperPending = false;
  534. if (userId != mCurrentUserId) return;
  535. if (bindWallpaperComponentLocked(defaultFailed
  536. ? IMAGE_WALLPAPER
  537. : null, true, false, wallpaper, reply)) {
  538. return;
  539. }
  540. } catch (IllegalArgumentException e1) {
  541. e = e1;
  542. } finally {
  543. Binder.restoreCallingIdentity(ident);
  544. }
  545. // This can happen if the default wallpaper component doesn't
  546. // exist. This should be a system configuration problem, but
  547. // let's not let it crash the system and just live with no
  548. // wallpaper.
  549. Slog.e(TAG, "Default wallpaper component not found!", e);
  550. clearWallpaperComponentLocked(wallpaper);
  551. if (reply != null) {
  552. try {
  553. reply.sendResult(null);
  554. } catch (RemoteException e1) {
  555. }
  556. }
  557. }
  558. public boolean hasNamedWallpaper(String name) {
  559. synchronized (mLock) {
  560. List<UserInfo> users;
  561. long ident = Binder.clearCallingIdentity();
  562. try {
  563. users = ((UserManager) mContext.getSystemService(Context.USER_SERVICE)).getUsers();
  564. } finally {
  565. Binder.restoreCallingIdentity(ident);
  566. }
  567. for (UserInfo user: users) {
  568. WallpaperData wd = mWallpaperMap.get(user.id);
  569. if (wd == null) {
  570. // User hasn't started yet, so load her settings to peek at the wallpaper
  571. loadSettingsLocked(user.id);
  572. wd = mWallpaperMap.get(user.id);
  573. }
  574. if (wd != null && name.equals(wd.name)) {
  575. return true;
  576. }
  577. }
  578. }
  579. return false;
  580. }
  581. private Point getDefaultDisplaySize() {
  582. Point p = new Point();
  583. WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
  584. Display d = wm.getDefaultDisplay();
  585. d.getRealSize(p);
  586. return p;
  587. }
  588. public void setDimensionHints(int width, int height) throws RemoteException {
  589. checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS);
  590. synchronized (mLock) {
  591. int userId = UserHandle.getCallingUserId();
  592. WallpaperData wallpaper = mWallpaperMap.get(userId);
  593. if (wallpaper == null) {
  594. throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
  595. }
  596. if (width <= 0 || height <= 0) {
  597. throw new IllegalArgumentException("width and height must be > 0");
  598. }
  599. // Make sure it is at least as large as the display.
  600. Point displaySize = getDefaultDisplaySize();
  601. width = Math.max(width, displaySize.x);
  602. height = Math.max(height, displaySize.y);
  603. if (width != wallpaper.width || height != wallpaper.height) {
  604. wallpaper.width = width;
  605. wallpaper.height = height;
  606. saveSettingsLocked(wallpaper);
  607. if (mCurrentUserId != userId) return; // Don't change the properties now
  608. if (wallpaper.connection != null) {
  609. if (wallpaper.connection.mEngine != null) {
  610. try {
  611. wallpaper.connection.mEngine.setDesiredSize(
  612. width, height);
  613. } catch (RemoteException e) {
  614. }
  615. notifyCallbacksLocked(wallpaper);
  616. } else if (wallpaper.connection.mService != null) {
  617. // We've attached to the service but the engine hasn't attached back to us
  618. // yet. This means it will be created with the previous dimensions, so we
  619. // need to update it to the new dimensions once it attaches.
  620. wallpaper.connection.mDimensionsChanged = true;
  621. }
  622. }
  623. }
  624. }
  625. }
  626. public int getWidthHint() throws RemoteException {
  627. synchronized (mLock) {
  628. WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
  629. return wallpaper.width;
  630. }
  631. }
  632. public int getHeightHint() throws RemoteException {
  633. synchronized (mLock) {
  634. WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId());
  635. return wallpaper.height;
  636. }
  637. }
  638. public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb,
  639. Bundle outParams) {
  640. synchronized (mLock) {
  641. // This returns the current user's wallpaper, if called by a system service. Else it
  642. // returns the wallpaper for the calling user.
  643. int callingUid = Binder.getCallingUid();
  644. int wallpaperUserId = 0;
  645. if (callingUid == android.os.Process.SYSTEM_UID) {
  646. wallpaperUserId = mCurrentUserId;
  647. } else {
  648. wallpaperUserId = UserHandle.getUserId(callingUid);
  649. }
  650. WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId);
  651. try {
  652. if (outParams != null) {
  653. outParams.putInt("width", wallpaper.width);
  654. outParams.putInt("height", wallpaper.height);
  655. }
  656. wallpaper.callbacks.register(cb);
  657. File f = new File(getWallpaperDir(wallpaperUserId), WALLPAPER);
  658. if (!f.exists()) {
  659. return null;
  660. }
  661. return ParcelFileDescriptor.open(f, MODE_READ_ONLY);
  662. } catch (FileNotFoundException e) {
  663. /* Shouldn't happen as we check to see if the file exists */
  664. Slog.w(TAG, "Error getting wallpaper", e);
  665. }
  666. return null;
  667. }
  668. }
  669. public WallpaperInfo getWallpaperInfo() {
  670. int userId = UserHandle.getCallingUserId();
  671. synchronized (mLock) {
  672. WallpaperData wallpaper = mWallpaperMap.get(userId);
  673. if (wallpaper.connection != null) {
  674. return wallpaper.connection.mInfo;
  675. }
  676. return null;
  677. }
  678. }
  679. public ParcelFileDescriptor setWallpaper(String name) {
  680. checkPermission(android.Manifest.permission.SET_WALLPAPER);
  681. synchronized (mLock) {
  682. if (DEBUG) Slog.v(TAG, "setWallpaper");
  683. int userId = UserHandle.getCallingUserId();
  684. WallpaperData wallpaper = mWallpaperMap.get(userId);
  685. if (wallpaper == null) {
  686. throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
  687. }
  688. final long ident = Binder.clearCallingIdentity();
  689. try {
  690. ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name, wallpaper);
  691. if (pfd != null) {
  692. wallpaper.imageWallpaperPending = true;
  693. }
  694. return pfd;
  695. } finally {
  696. Binder.restoreCallingIdentity(ident);
  697. }
  698. }
  699. }
  700. ParcelFileDescriptor updateWallpaperBitmapLocked(String name, WallpaperData wallpaper) {
  701. if (name == null) name = "";
  702. try {
  703. File dir = getWallpaperDir(wallpaper.userId);
  704. if (!dir.exists()) {
  705. dir.mkdir();
  706. FileUtils.setPermissions(
  707. dir.getPath(),
  708. FileUtils.S_IRWXU|FileUtils.S_IRWXG|FileUtils.S_IXOTH,
  709. -1, -1);
  710. }
  711. File file = new File(dir, WALLPAPER);
  712. ParcelFileDescriptor fd = ParcelFileDescriptor.open(file,
  713. MODE_CREATE|MODE_READ_WRITE);
  714. if (!SELinux.restorecon(file)) {
  715. return null;
  716. }
  717. wallpaper.name = name;
  718. return fd;
  719. } catch (FileNotFoundException e) {
  720. Slog.w(TAG, "Error setting wallpaper", e);
  721. }
  722. return null;
  723. }
  724. public void setWallpaperComponent(ComponentName name) {
  725. checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT);
  726. synchronized (mLock) {
  727. if (DEBUG) Slog.v(TAG, "setWallpaperComponent name=" + name);
  728. int userId = UserHandle.getCallingUserId();
  729. WallpaperData wallpaper = mWallpaperMap.get(userId);
  730. if (wallpaper == null) {
  731. throw new IllegalStateException("Wallpaper not yet initialized for user " + userId);
  732. }
  733. final long ident = Binder.clearCallingIdentity();
  734. try {
  735. wallpaper.imageWallpaperPending = false;
  736. bindWallpaperComponentLocked(name, false, true, wallpaper, null);
  737. } finally {
  738. Binder.restoreCallingIdentity(ident);
  739. }
  740. }
  741. }
  742. boolean bindWallpaperComponentLocked(ComponentName componentName, boolean force,
  743. boolean fromUser, WallpaperData wallpaper, IRemoteCallback reply) {
  744. if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: componentName=" + componentName);
  745. // Has the component changed?
  746. if (!force) {
  747. if (wallpaper.connection != null) {
  748. if (wallpaper.wallpaperComponent == null) {
  749. if (componentName == null) {
  750. if (DEBUG) Slog.v(TAG, "bindWallpaperComponentLocked: still using default");
  751. // Still using default wallpaper.
  752. return true;
  753. }
  754. } else if (wallpaper.wallpaperComponent.equals(componentName)) {
  755. // Changing to same wallpaper.
  756. if (DEBUG) Slog.v(TAG, "same wallpaper");
  757. return true;
  758. }
  759. }
  760. }
  761. try {
  762. if (componentName == null) {
  763. String defaultComponent =
  764. mContext.getString(com.android.internal.R.string.default_wallpaper_component);
  765. if (defaultComponent != null) {
  766. // See if there is a default wallpaper component specified
  767. componentName = ComponentName.unflattenFromString(defaultComponent);
  768. if (DEBUG) Slog.v(TAG, "Use default component wallpaper:" + componentName);
  769. }
  770. if (componentName == null) {
  771. // Fall back to static image wallpaper
  772. componentName = IMAGE_WALLPAPER;
  773. //clearWallpaperComponentLocked();
  774. //return;
  775. if (DEBUG) Slog.v(TAG, "Using image wallpaper");
  776. }
  777. }
  778. int serviceUserId = wallpaper.userId;
  779. ServiceInfo si = mIPackageManager.getServiceInfo(componentName,
  780. PackageManager.GET_META_DATA | PackageManager.GET_PERMISSIONS, serviceUserId);
  781. if (si == null) {
  782. // The wallpaper component we're trying to use doesn't exist
  783. Slog.w(TAG, "Attempted wallpaper " + componentName + " is unavailable");
  784. return false;
  785. }
  786. if (!android.Manifest.permission.BIND_WALLPAPER.equals(si.permission)) {
  787. String msg = "Selected service does not require "
  788. + android.Manifest.permission.BIND_WALLPAPER
  789. + ": " + componentName;
  790. if (fromUser) {
  791. throw new SecurityException(msg);
  792. }
  793. Slog.w(TAG, msg);
  794. return false;
  795. }
  796. WallpaperInfo wi = null;
  797. Intent intent = new Intent(WallpaperService.SERVICE_INTERFACE);
  798. if (componentName != null && !componentName.equals(IMAGE_WALLPAPER)) {
  799. // Make sure the selected service is actually a wallpaper service.
  800. List<ResolveInfo> ris =
  801. mIPackageManager.queryIntentServices(intent,
  802. intent.resolveTypeIfNeeded(mContext.getContentResolver()),
  803. PackageManager.GET_META_DATA, serviceUserId);
  804. for (int i=0; i<ris.size(); i++) {
  805. ServiceInfo rsi = ris.get(i).serviceInfo;
  806. if (rsi.name.equals(si.name) &&
  807. rsi.packageName.equals(si.packageName)) {
  808. try {
  809. wi = new WallpaperInfo(mContext, ris.get(i));
  810. } catch (XmlPullParserException e) {
  811. if (fromUser) {
  812. throw new IllegalArgumentException(e);
  813. }
  814. Slog.w(TAG, e);
  815. return false;
  816. } catch (IOException e) {
  817. if (fromUser) {
  818. throw new IllegalArgumentException(e);
  819. }
  820. Slog.w(TAG, e);
  821. return false;
  822. }
  823. break;
  824. }
  825. }
  826. if (wi == null) {
  827. String msg = "Selected service is not a wallpaper: "
  828. + componentName;
  829. if (fromUser) {
  830. throw new SecurityException(msg);
  831. }
  832. Slog.w(TAG, msg);
  833. return false;
  834. }
  835. }
  836. // Bind the service!
  837. if (DEBUG) Slog.v(TAG, "Binding to:" + componentName);
  838. WallpaperConnection newConn = new WallpaperConnection(wi, wallpaper);
  839. intent.setComponent(componentName);
  840. intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
  841. com.android.internal.R.string.wallpaper_binding_label);
  842. intent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivityAsUser(
  843. mContext, 0,
  844. Intent.createChooser(new Intent(Intent.ACTION_SET_WALLPAPER),
  845. mContext.getText(com.android.internal.R.string.chooser_wallpaper)),
  846. 0, null, new UserHandle(serviceUserId)));
  847. if (!mContext.bindServiceAsUser(intent, newConn,
  848. Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI,
  849. new UserHandle(serviceUserId))) {
  850. String msg = "Unable to bind service: "
  851. + componentName;
  852. if (fromUser) {
  853. throw new IllegalArgumentException(msg);
  854. }
  855. Slog.w(TAG, msg);
  856. return false;
  857. }
  858. if (wallpaper.userId == mCurrentUserId && mLastWallpaper != null) {
  859. detachWallpaperLocked(mLastWallpaper);
  860. }
  861. wallpaper.wallpaperComponent = componentName;
  862. wallpaper.connection = newConn;
  863. wallpaper.lastDiedTime = SystemClock.uptimeMillis();
  864. newConn.mReply = reply;
  865. try {
  866. if (wallpaper.userId == mCurrentUserId) {
  867. if (DEBUG)
  868. Slog.v(TAG, "Adding window token: " + newConn.mToken);
  869. mIWindowManager.addWindowToken(newConn.mToken,
  870. WindowManager.LayoutParams.TYPE_WALLPAPER);
  871. mLastWallpaper = wallpaper;
  872. }
  873. } catch (RemoteException e) {
  874. }
  875. } catch (RemoteException e) {
  876. String msg = "Remote exception for " + componentName + "\n" + e;
  877. if (fromUser) {
  878. throw new IllegalArgumentException(msg);
  879. }
  880. Slog.w(TAG, msg);
  881. return false;
  882. }
  883. return true;
  884. }
  885. void detachWallpaperLocked(WallpaperData wallpaper) {
  886. if (wallpaper.connection != null) {
  887. if (wallpaper.connection.mReply != null) {
  888. try {
  889. wallpaper.connection.mReply.sendResult(null);
  890. } catch (RemoteException e) {
  891. }
  892. wallpaper.connection.mReply = null;
  893. }
  894. if (wallpaper.connection.mEngine != null) {
  895. try {
  896. wallpaper.connection.mEngine.destroy();
  897. } catch (RemoteException e) {
  898. }
  899. }
  900. mContext.unbindService(wallpaper.connection);
  901. try {
  902. if (DEBUG)
  903. Slog.v(TAG, "Removing window token: " + wallpaper.connection.mToken);
  904. mIWindowManager.removeWindowToken(wallpaper.connection.mToken);
  905. } catch (RemoteException e) {
  906. }
  907. wallpaper.connection.mService = null;
  908. wallpaper.connection.mEngine = null;
  909. wallpaper.connection = null;
  910. }
  911. }
  912. void clearWallpaperComponentLocked(WallpaperData wallpaper) {
  913. wallpaper.wallpaperComponent = null;
  914. detachWallpaperLocked(wallpaper);
  915. }
  916. void attachServiceLocked(WallpaperConnection conn, WallpaperData wallpaper) {
  917. try {
  918. conn.mService.attach(conn, conn.mToken,
  919. WindowManager.LayoutParams.TYPE_WALLPAPER, false,
  920. wallpaper.width, wallpaper.height);
  921. } catch (RemoteException e) {
  922. Slog.w(TAG, "Failed attaching wallpaper; clearing", e);
  923. if (!wallpaper.wallpaperUpdating) {
  924. bindWallpaperComponentLocked(null, false, false, wallpaper, null);
  925. }
  926. }
  927. }
  928. private void notifyCallbacksLocked(WallpaperData wallpaper) {
  929. final int n = wallpaper.callbacks.beginBroadcast();
  930. for (int i = 0; i < n; i++) {
  931. try {
  932. wallpaper.callbacks.getBroadcastItem(i).onWallpaperChanged();
  933. } catch (RemoteException e) {
  934. // The RemoteCallbackList will take care of removing
  935. // the dead object for us.
  936. }
  937. }
  938. wallpaper.callbacks.finishBroadcast();
  939. final Intent intent = new Intent(Intent.ACTION_WALLPAPER_CHANGED);
  940. mContext.sendBroadcastAsUser(intent, new UserHandle(mCurrentUserId));
  941. }
  942. private void checkPermission(String permission) {
  943. if (PackageManager.PERMISSION_GRANTED!= mContext.checkCallingOrSelfPermission(permission)) {
  944. throw new SecurityException("Access denied to process: " + Binder.getCallingPid()
  945. + ", must have permission " + permission);
  946. }
  947. }
  948. private static JournaledFile makeJournaledFile(int userId) {
  949. final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath();
  950. return new JournaledFile(new File(base), new File(base + ".tmp"));
  951. }
  952. private void saveSettingsLocked(WallpaperData wallpaper) {
  953. JournaledFile journal = makeJournaledFile(wallpaper.userId);
  954. FileOutputStream stream = null;
  955. try {
  956. stream = new FileOutputStream(journal.chooseForWrite(), false);
  957. XmlSerializer out = new FastXmlSerializer();
  958. out.setOutput(stream, "utf-8");
  959. out.startDocument(null, true);
  960. out.startTag(null, "wp");
  961. out.attribute(null, "width", Integer.toString(wallpaper.width));
  962. out.attribute(null, "height", Integer.toString(wallpaper.height));
  963. out.attribute(null, "name", wallpaper.name);
  964. if (wallpaper.wallpaperComponent != null
  965. && !wallpaper.wallpaperComponent.equals(IMAGE_WALLPAPER)) {
  966. out.attribute(null, "component",
  967. wallpaper.wallpaperComponent.flattenToShortString());
  968. }
  969. out.endTag(null, "wp");
  970. out.endDocument();
  971. stream.close();
  972. journal.commit();
  973. } catch (IOException e) {
  974. try {
  975. if (stream != null) {
  976. stream.close();
  977. }
  978. } catch (IOException ex) {
  979. // Ignore
  980. }
  981. journal.rollback();
  982. }
  983. }
  984. private void migrateFromOld() {
  985. File oldWallpaper = new File(WallpaperBackupHelper.WALLPAPER_IMAGE_KEY);
  986. File oldInfo = new File(WallpaperBackupHelper.WALLPAPER_INFO_KEY);
  987. if (oldWallpaper.exists()) {
  988. File newWallpaper = new File(getWallpaperDir(0), WALLPAPER);
  989. oldWallpaper.renameTo(newWallpaper);
  990. }
  991. if (oldInfo.exists()) {
  992. File newInfo = new File(getWallpaperDir(0), WALLPAPER_INFO);
  993. oldInfo.renameTo(newInfo);
  994. }
  995. }
  996. private void loadSettingsLocked(int userId) {
  997. if (DEBUG) Slog.v(TAG, "loadSettingsLocked");
  998. JournaledFile journal = makeJournaledFile(userId);
  999. FileInputStream stream = null;
  1000. File file = journal.chooseForRead();
  1001. if (!file.exists()) {
  1002. // This should only happen one time, when upgrading from a legacy system
  1003. migrateFromOld();
  1004. }
  1005. WallpaperData wallpaper = mWallpaperMap.get(userId);
  1006. if (wallpaper == null) {
  1007. wallpaper = new WallpaperData(userId);
  1008. mWallpaperMap.put(userId, wallpaper);
  1009. }
  1010. boolean success = false;
  1011. try {
  1012. stream = new FileInputStream(file);
  1013. XmlPullParser parser = Xml.newPullParser();
  1014. parser.setInput(stream, null);
  1015. int type;
  1016. do {
  1017. type = parser.next();
  1018. if (type == XmlPullParser.START_TAG) {
  1019. String tag = parser.getName();
  1020. if ("wp".equals(tag)) {
  1021. wallpaper.width = Integer.parseInt(parser.getAttributeValue(null, "width"));
  1022. wallpaper.height = Integer.parseInt(parser
  1023. .getAttributeValue(null, "height"));
  1024. wallpaper.name = parser.getAttributeValue(null, "name");
  1025. String comp = parser.getAttributeValue(null, "component");
  1026. wallpaper.nextWallpaperComponent = comp != null
  1027. ? ComponentName.unflattenFromString(comp)
  1028. : null;
  1029. if (wallpaper.nextWallpaperComponent == null
  1030. || "android".equals(wallpaper.nextWallpaperComponent
  1031. .getPackageName())) {
  1032. wallpaper.nextWallpaperComponent = IMAGE_WALLPAPER;
  1033. }
  1034. if (DEBUG) {
  1035. Slog.v(TAG, "mWidth:" + wallpaper.width);
  1036. Slog.v(TAG, "mHeight:" + wallpaper.height);
  1037. Slog.v(TAG, "mName:" + wallpaper.name);
  1038. Slog.v(TAG, "mNextWallpaperComponent:"
  1039. + wallpaper.nextWallpaperComponent);
  1040. }
  1041. }
  1042. }
  1043. } while (type != XmlPullParser.END_DOCUMENT);
  1044. success = true;
  1045. } catch (FileNotFoundException e) {
  1046. Slog.w(TAG, "no current wallpaper -- first boot?");
  1047. } catch (NullPointerException e) {
  1048. Slog.w(TAG, "failed parsing " + file + " " + e);
  1049. } catch (NumberFormatException e) {
  1050. Slog.w(TAG, "failed parsing " + file + " " + e);
  1051. } catch (XmlPullParserException e) {
  1052. Slog.w(TAG, "failed parsing " + file + " " + e);
  1053. } catch (IOException e) {
  1054. Slog.w(TAG, "failed parsing " + file + " " + e);
  1055. } catch (IndexOutOfBoundsException e) {
  1056. Slog.w(TAG, "failed parsing " + file + " " + e);
  1057. }
  1058. try {
  1059. if (stream != null) {
  1060. stream.close();
  1061. }
  1062. } catch (IOException e) {
  1063. // Ignore
  1064. }
  1065. if (!success) {
  1066. wallpaper.width = -1;
  1067. wallpaper.height = -1;
  1068. wallpaper.name = "";
  1069. }
  1070. // We always want to have some reasonable width hint.
  1071. int baseSize = getMaximumSizeDimension();
  1072. if (wallpaper.width < baseSize) {
  1073. wallpaper.width = baseSize;
  1074. }
  1075. if (wallpaper.height < baseSize) {
  1076. wallpaper.height = baseSize;
  1077. }
  1078. }
  1079. private int getMaximumSizeDimension() {
  1080. WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
  1081. Display d = wm.getDefaultDisplay();
  1082. return d.getMaximumSizeDimension();
  1083. }
  1084. // Called by SystemBackupAgent after files are restored to disk.
  1085. void settingsRestored() {
  1086. // TODO: If necessary, make it work for secondary users as well. This currently assumes
  1087. // restores only to the primary user
  1088. if (DEBUG) Slog.v(TAG, "settingsRestored");
  1089. WallpaperData wallpaper = null;
  1090. boolean success = false;
  1091. synchronized (mLock) {
  1092. loadSettingsLocked(0);
  1093. wallpaper = mWallpaperMap.get(0);
  1094. if (wallpaper.nextWallpaperComponent != null
  1095. && !wallpaper.nextWallpaperComponent.equals(IMAGE_WALLPAPER)) {
  1096. if (!bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
  1097. wallpaper, null)) {
  1098. // No such live wallpaper or other failure; fall back to the default
  1099. // live wallpaper (since the profile being restored indicated that the
  1100. // user had selected a live rather than static one).
  1101. bindWallpaperComponentLocked(null, false, false, wallpaper, null);
  1102. }
  1103. success = true;
  1104. } else {
  1105. // If there's a wallpaper name, we use that. If that can't be loaded, then we
  1106. // use the default.
  1107. if ("".equals(wallpaper.name)) {
  1108. if (DEBUG) Slog.v(TAG, "settingsRestored: name is empty");
  1109. success = true;
  1110. } else {
  1111. if (DEBUG) Slog.v(TAG, "settingsRestored: attempting to restore named resource");
  1112. success = restoreNamedResourceLocked(wallpaper);
  1113. }
  1114. if (DEBUG) Slog.v(TAG, "settingsRestored: success=" + success);
  1115. if (success) {
  1116. bindWallpaperComponentLocked(wallpaper.nextWallpaperComponent, false, false,
  1117. wallpaper, null);
  1118. }
  1119. }
  1120. }
  1121. if (!success) {
  1122. Slog.e(TAG, "Failed to restore wallpaper: '" + wallpaper.name + "'");
  1123. wallpaper.name = "";
  1124. getWallpaperDir(0).delete();
  1125. }
  1126. synchronized (mLock) {
  1127. saveSettingsLocked(wallpaper);
  1128. }
  1129. }
  1130. boolean restoreNamedResourceLocked(WallpaperData wallpaper) {
  1131. if (wallpaper.name.length() > 4 && "res:".equals(wallpaper.name.substring(0, 4))) {
  1132. String resName = wallpaper.name.substring(4);
  1133. String pkg = null;
  1134. int colon = resName.indexOf(':');
  1135. if (colon > 0) {
  1136. pkg = resName.substring(0, colon);
  1137. }
  1138. String ident = null;
  1139. int slash = resName.lastIndexOf('/');
  1140. if (slash > 0) {
  1141. ident = resName.substring(slash+1);
  1142. }
  1143. String type = null;
  1144. if (colon > 0 && slash > 0 && (slash-colon) > 1) {
  1145. type = resName.substring(colon+1, slash);
  1146. }
  1147. if (pkg != null && ident != null && type != null) {
  1148. int resId = -1;
  1149. InputStream res = null;
  1150. FileOutputStream fos = null;
  1151. try {
  1152. Context c = mContext.createPackageContext(pkg, Context.CONTEXT_RESTRICTED);
  1153. Resources r = c.getResources();
  1154. resId = r.getIdentifier(resName, null, null);
  1155. if (resId == 0) {
  1156. Slog.e(TAG, "couldn't resolve identifier pkg=" + pkg + " type=" + type
  1157. + " ident=" + ident);
  1158. return false;
  1159. }
  1160. res = r.openRawResource(resId);
  1161. if (wallpaper.wallpaperFile.exists()) {
  1162. wallpaper.wallpaperFile.delete();
  1163. }
  1164. fos = new FileOutputStream(wallpaper.wallpaperFile);
  1165. byte[] buffer = new byte[32768];
  1166. int amt;
  1167. while ((amt=res.read(buffer)) > 0) {
  1168. fos.write(buffer, 0, amt);
  1169. }
  1170. // mWallpaperObserver will notice the close and send the change broadcast
  1171. Slog.v(TAG, "Restored wallpaper: " + resName);
  1172. return true;
  1173. } catch (NameNotFoundException e) {
  1174. Slog.e(TAG, "Package name " + pkg + " not found");
  1175. } catch (Resources.NotFoundException e) {
  1176. Slog.e(TAG, "Resource not found: " + resId);
  1177. } catch (IOException e) {
  1178. Slog.e(TAG, "IOException while restoring wallpaper ", e);
  1179. } finally {
  1180. if (res != null) {
  1181. try {
  1182. res.close();
  1183. } catch (IOException ex) {}
  1184. }
  1185. if (fos != null) {
  1186. FileUtils.sync(fos);
  1187. try {
  1188. fos.close();
  1189. } catch (IOException ex) {}
  1190. }
  1191. }
  1192. }
  1193. }
  1194. return false;
  1195. }
  1196. @Override
  1197. protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
  1198. if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
  1199. != PackageManager.PERMISSION_GRANTED) {
  1200. pw.println("Permission Denial: can't dump wallpaper service from from pid="
  1201. + Binder.getCallingPid()
  1202. + ", uid=" + Binder.getCallingUid());
  1203. return;
  1204. }
  1205. synchronized (mLock) {
  1206. pw.println("Current Wallpaper Service state:");
  1207. for (int i = 0; i < mWallpaperMap.size(); i++) {
  1208. WallpaperData wallpaper = mWallpaperMap.valueAt(i);
  1209. pw.println(" User " + wallpaper.userId + ":");
  1210. pw.print(" mWidth=");
  1211. pw.print(wallpaper.width);
  1212. pw.print(" mHeight=");
  1213. pw.println(wallpaper.height);
  1214. pw.print(" mName=");
  1215. pw.println(wallpaper.name);
  1216. pw.print(" mWallpaperComponent=");
  1217. pw.println(wallpaper.wallpaperComponent);
  1218. if (wallpaper.connection != null) {
  1219. WallpaperConnection conn = wallpaper.connection;
  1220. pw.print(" Wallpaper connection ");
  1221. pw.print(conn);
  1222. pw.println(":");
  1223. if (conn.mInfo != null) {
  1224. pw.print(" mInfo.component=");
  1225. pw.println(conn.mInfo.getComponent());
  1226. }
  1227. pw.print(" mToken=");
  1228. pw.println(conn.mToken);
  1229. pw.print(" mService=");
  1230. pw.println(conn.mService);
  1231. pw.print(" mEngine=");
  1232. pw.println(conn.mEngine);
  1233. pw.print(" mLastDiedTime=");
  1234. pw.println(wallpaper.lastDiedTime - SystemClock.uptimeMillis());
  1235. }
  1236. }
  1237. }
  1238. }
  1239. }