1 package android.service.dreams; 2 3 import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT; 4 5 import java.io.FileDescriptor; 6 import java.io.PrintWriter; 7 8 import com.android.internal.view.IInputMethod; 9 10 import android.content.ComponentName; 11 import android.content.Context; 12 import android.content.Intent; 13 import android.content.ServiceConnection; 14 import android.content.pm.PackageManager; 15 import android.os.Binder; 16 import android.os.IBinder; 17 import android.os.RemoteException; 18 import android.os.ServiceManager; 19 import android.os.SystemClock; 20 import android.provider.Settings; 21 import android.util.Log; 22 import android.util.Slog; 23 import android.view.IWindowManager; 24 import android.view.WindowManager; 25 26 /** 27 * 28 * @hide 29 * 30 */ 31 32 public class DreamManagerService 33 extends IDreamManager.Stub 34 implements ServiceConnection 35 { 36 private static final boolean DEBUG = true; 37 private static final String TAG = "DreamManagerService"; 38 39 final Object mLock = new Object[0]; 40 41 private Context mContext; 42 private IWindowManager mIWindowManager; 43 44 private ComponentName mCurrentDreamComponent; 45 private IDreamService mCurrentDream; 46 private Binder mCurrentDreamToken; 47 48 public DreamManagerService(Context context) { 49 if (DEBUG) Slog.v(TAG, "DreamManagerService startup"); 50 mContext = context; 51 mIWindowManager = IWindowManager.Stub.asInterface( 52 ServiceManager.getService(Context.WINDOW_SERVICE)); 53 } 54 55 private void checkPermission(String permission) { 56 if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) { 57 throw new SecurityException("Access denied to process: " + Binder.getCallingPid() 58 + ", must have permission " + permission); 59 } 60 } 61 62 // IDreamManager method 63 public void dream() { 64 ComponentName name = getDreamComponent(); 65 if (name != null) { 66 synchronized (mLock) { 67 final long ident = Binder.clearCallingIdentity(); 68 try { 69 bindDreamComponentL(name, false); 70 } finally { 71 Binder.restoreCallingIdentity(ident); 72 } 73 } 74 } 75 } 76 77 // IDreamManager method 78 public void setDreamComponent(ComponentName name) { 79 Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString()); 80 } 81 82 // IDreamManager method 83 public ComponentName getDreamComponent() { 84 // TODO(dsandler) don't load this every time, watch the value 85 String component = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENT); 86 if (component == null) { 87 component = mContext.getResources().getString( 88 com.android.internal.R.string.config_defaultDreamComponent); 89 } 90 if (component != null) { 91 return ComponentName.unflattenFromString(component); 92 } else { 93 return null; 94 } 95 } 96 97 // IDreamManager method 98 public void testDream(ComponentName name) { 99 if (DEBUG) Slog.v(TAG, "startDream name=" + name 100 + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 101 // checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); 102 synchronized (mLock) { 103 final long ident = Binder.clearCallingIdentity(); 104 try { 105 bindDreamComponentL(name, true); 106 } finally { 107 Binder.restoreCallingIdentity(ident); 108 } 109 } 110 } 111 112 // IDreamManager method 113 public void awaken() { 114 if (DEBUG) Slog.v(TAG, "awaken()"); 115 synchronized (mLock) { 116 if (mCurrentDream != null) { 117 mContext.unbindService(this); 118 } 119 } 120 } 121 122 public void bindDreamComponentL(ComponentName componentName, boolean test) { 123 if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName 124 + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); 125 126 Intent intent = new Intent(Intent.ACTION_MAIN) 127 .setComponent(componentName) 128 .addFlags( 129 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS 130 ) 131 .putExtra("android.dreams.TEST", test); 132 133 if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { 134 Slog.w(TAG, "unable to bind service: " + componentName); 135 return; 136 } 137 mCurrentDreamComponent = componentName; 138 mCurrentDreamToken = new Binder(); 139 try { 140 if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurrentDreamToken 141 + " for window type: " + WindowManager.LayoutParams.TYPE_DREAM); 142 mIWindowManager.addWindowToken(mCurrentDreamToken, 143 WindowManager.LayoutParams.TYPE_DREAM); 144 } catch (RemoteException e) { 145 Slog.w(TAG, "Unable to add window token. Proceed at your own risk."); 146 } 147 148 } 149 150 @Override 151 public void onServiceConnected(ComponentName name, IBinder service) { 152 if (DEBUG) Slog.v(TAG, "connected to dream: " + name + " binder=" + service + " thread=" + Thread.currentThread().getId()); 153 154 mCurrentDream = IDreamService.Stub.asInterface(service); 155 try { 156 if (DEBUG) Slog.v(TAG, "attaching with token:" + mCurrentDreamToken); 157 mCurrentDream.attach(mCurrentDreamToken); 158 } catch (RemoteException ex) { 159 Slog.w(TAG, "Unable to send window token to dream:" + ex); 160 } 161 } 162 163 @Override 164 public void onServiceDisconnected(ComponentName name) { 165 if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream); 166 mCurrentDream = null; 167 mCurrentDreamToken = null; 168 } 169 170 @Override 171 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 172 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); 173 174 pw.println("Dreamland:"); 175 pw.print(" component="); pw.println(mCurrentDreamComponent); 176 pw.print(" token="); pw.println(mCurrentDreamToken); 177 pw.print(" dream="); pw.println(mCurrentDream); 178 } 179 180 public void systemReady() { 181 if (DEBUG) Slog.v(TAG, "ready to dream!"); 182 } 183 184 } 185