Loading Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,8 @@ LOCAL_SRC_FILES += \ core/java/android/os/IRemoteCallback.aidl \ core/java/android/os/IUpdateLock.aidl \ core/java/android/os/IVibratorService.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ core/java/android/service/wallpaper/IWallpaperConnection.aidl \ core/java/android/service/wallpaper/IWallpaperEngine.aidl \ core/java/android/service/wallpaper/IWallpaperService.aidl \ Loading core/java/android/service/dreams/Dream.java 0 → 100644 +392 −0 Original line number Diff line number Diff line /** * */ package android.service.dreams; import com.android.internal.policy.PolicyManager; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.graphics.drawable.ColorDrawable; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.view.ActionMode; import android.view.IWindowManager; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.view.WindowManager; import android.view.WindowManagerImpl; /** * @hide * */ public class Dream extends Service implements Window.Callback { private final static boolean DEBUG = true; private final static String TAG = "Dream"; /** * The {@link Intent} that must be declared as handled by the service. * To be supported, the service must also require the * {@link android.Manifest.permission#BIND_WALLPAPER} permission so * that other applications can not abuse it. */ @SdkConstant(SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.service.dreams.Dream"; private Window mWindow; private WindowManager mWindowManager; private IDreamManager mSandman; private boolean mInteractive; final Handler mHandler = new Handler(); boolean mFinished = false; // begin Window.Callback methods @Override public boolean dispatchKeyEvent(KeyEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchKeyEvent(event); } @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchKeyShortcutEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchTouchEvent(event); } @Override public boolean dispatchTrackballEvent(MotionEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchTrackballEvent(event); } @Override public boolean dispatchGenericMotionEvent(MotionEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchGenericMotionEvent(event); } @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { return false; } @Override public View onCreatePanelView(int featureId) { return null; } @Override public boolean onCreatePanelMenu(int featureId, Menu menu) { return false; } @Override public boolean onPreparePanel(int featureId, View view, Menu menu) { return false; } @Override public boolean onMenuOpened(int featureId, Menu menu) { return false; } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { return false; } @Override public void onWindowAttributesChanged(LayoutParams attrs) { } @Override public void onContentChanged() { } @Override public void onWindowFocusChanged(boolean hasFocus) { } @Override public void onAttachedToWindow() { mWindow.addFlags( WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED ); lightsOut(); } @Override public void onDetachedFromWindow() { } @Override public void onPanelClosed(int featureId, Menu menu) { } @Override public boolean onSearchRequested() { return false; } @Override public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) { return null; } @Override public void onActionModeStarted(ActionMode mode) { } @Override public void onActionModeFinished(ActionMode mode) { } // end Window.Callback methods public WindowManager getWindowManager() { return mWindowManager; } public Window getWindow() { return mWindow; } /** * Called when this Dream is constructed. Place your initialization here. * * Subclasses must call through to the superclass implementation. */ @Override public void onCreate() { super.onCreate(); if (DEBUG) Slog.v(TAG, "Dream created on thread " + Thread.currentThread().getId()); mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams")); } /** * Called when this Dream is started. Place your initialization here. * * Subclasses must call through to the superclass implementation. * * XXX(dsandler) Might want to make this final and have a different method for clients to override */ @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } /** * Inflate a layout resource and set it to be the content view for this Dream. * Behaves similarly to {@link android.app.Activity#setContentView(int)}. * * @param layoutResID Resource ID to be inflated. * * @see #setContentView(android.view.View) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); } /** * Set a view to be the content view for this Dream. * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)}, * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view. * * @param view The desired content to display. * * @see #setContentView(int) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView(View view) { getWindow().setContentView(view); } /** * Set a view to be the content view for this Dream. * Behaves similarly to * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}. * * @param view The desired content to display. * @param params Layout parameters for the view. * * @see #setContentView(android.view.View) * @see #setContentView(int) */ public void setContentView(View view, ViewGroup.LayoutParams params) { getWindow().setContentView(view, params); } /** * Add a view to the Dream's window, leaving other content views in place. * * @param view The desired content to display. * @param params Layout parameters for the view. */ public void addContentView(View view, ViewGroup.LayoutParams params) { getWindow().addContentView(view, params); } /** * @param mInteractive the mInteractive to set */ public void setInteractive(boolean mInteractive) { this.mInteractive = mInteractive; } /** * @return the mInteractive */ public boolean isInteractive() { return mInteractive; } /** Convenience method for setting View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. */ protected void lightsOut() { // turn the lights down low final View v = mWindow.getDecorView(); if (v != null) { v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); } } /** * Finds a view that was identified by the id attribute from the XML that * was processed in {@link #onCreate}. * * @return The view if found or null otherwise. */ public View findViewById(int id) { return getWindow().findViewById(id); } /** * Called when this Dream is being removed from the screen and stopped. */ @Override public void onDestroy() { super.onDestroy(); mWindowManager.removeView(mWindow.getDecorView()); } /** * Creates a new dream window, attaches the current content view, and shows it. * * @param windowToken Binder to attach to the window to allow access to the correct window type. * @hide */ final /*package*/ void attach(IBinder windowToken) { if (DEBUG) Slog.v(TAG, "Dream attached on thread " + Thread.currentThread().getId()); mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); if (DEBUG) Slog.v(TAG, "attaching window token: " + windowToken + " to window of type " + WindowManager.LayoutParams.TYPE_DREAM); WindowManager.LayoutParams lp = mWindow.getAttributes(); lp.type = WindowManager.LayoutParams.TYPE_DREAM; lp.token = windowToken; lp.windowAnimations = com.android.internal.R.style.Animation_Dream; //WindowManagerImpl.getDefault().addView(mWindow.getDecorView(), lp); if (DEBUG) Slog.v(TAG, "created and attached window: " + mWindow); mWindow.setWindowManager(null, windowToken, "dream", true); mWindowManager = mWindow.getWindowManager(); // now make it visible mHandler.post(new Runnable(){ @Override public void run() { if (DEBUG) Slog.v(TAG, "Dream window added on thread " + Thread.currentThread().getId()); getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); }}); } /** * Stop the dream and wake up. * * After this method is called, the service will be stopped. */ public void finish() { if (mFinished) return; try { mSandman.awaken(); // assuming we were started by the DreamManager stopSelf(); // if launched via any other means mFinished = true; } catch (RemoteException ex) { // sigh } } class IDreamServiceWrapper extends IDreamService.Stub { public IDreamServiceWrapper() { } public void attach(IBinder windowToken) { Dream.this.attach(windowToken); } } /** * Implement to return the implementation of the internal accessibility * service interface. Subclasses should not override. */ @Override public final IBinder onBind(Intent intent) { return new IDreamServiceWrapper(); } } core/java/android/service/dreams/DreamManagerService.java 0 → 100644 +182 −0 Original line number Diff line number Diff line package android.service.dreams; import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT; import java.io.FileDescriptor; import java.io.PrintWriter; import com.android.internal.view.IInputMethod; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.provider.Settings; import android.util.Log; import android.util.Slog; import android.view.IWindowManager; import android.view.WindowManager; /** * * @hide * */ public class DreamManagerService extends IDreamManager.Stub implements ServiceConnection { private static final boolean DEBUG = true; private static final String TAG = "DreamManagerService"; final Object mLock = new Object[0]; private Context mContext; private IWindowManager mIWindowManager; private ComponentName mCurrentDreamComponent; private IDreamService mCurrentDream; private Binder mCurrentDreamToken; public DreamManagerService(Context context) { if (DEBUG) Slog.v(TAG, "DreamManagerService startup"); mContext = context; mIWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); } private void checkPermission(String permission) { if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) { throw new SecurityException("Access denied to process: " + Binder.getCallingPid() + ", must have permission " + permission); } } // IDreamManager method public void dream() { ComponentName name = getDreamComponent(); if (name != null) { synchronized (mLock) { final long ident = Binder.clearCallingIdentity(); try { bindDreamComponentL(name, false); } finally { Binder.restoreCallingIdentity(ident); } } } } // IDreamManager method public void setDreamComponent(ComponentName name) { Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString()); } // IDreamManager method public ComponentName getDreamComponent() { // TODO(dsandler) don't load this every time, watch the value String component = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENT); if (component == null) { component = mContext.getResources().getString( com.android.internal.R.string.config_defaultDreamComponent); } if (component != null) { return ComponentName.unflattenFromString(component); } else { return null; } } // IDreamManager method public void testDream(ComponentName name) { if (DEBUG) Slog.v(TAG, "startDream name=" + name + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); // checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); synchronized (mLock) { final long ident = Binder.clearCallingIdentity(); try { bindDreamComponentL(name, true); } finally { Binder.restoreCallingIdentity(ident); } } } // IDreamManager method public void awaken() { if (DEBUG) Slog.v(TAG, "awaken()"); synchronized (mLock) { if (mCurrentDream != null) { mContext.unbindService(this); } } } public void bindDreamComponentL(ComponentName componentName, boolean test) { if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); Intent intent = new Intent(Intent.ACTION_MAIN) .setComponent(componentName) .addFlags( Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS ) .putExtra("android.dreams.TEST", test); if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { Slog.w(TAG, "unable to bind service: " + componentName); return; } mCurrentDreamComponent = componentName; mCurrentDreamToken = new Binder(); try { if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurrentDreamToken + " for window type: " + WindowManager.LayoutParams.TYPE_DREAM); mIWindowManager.addWindowToken(mCurrentDreamToken, WindowManager.LayoutParams.TYPE_DREAM); } catch (RemoteException e) { Slog.w(TAG, "Unable to add window token. Proceed at your own risk."); } } @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG) Slog.v(TAG, "connected to dream: " + name + " binder=" + service + " thread=" + Thread.currentThread().getId()); mCurrentDream = IDreamService.Stub.asInterface(service); try { if (DEBUG) Slog.v(TAG, "attaching with token:" + mCurrentDreamToken); mCurrentDream.attach(mCurrentDreamToken); } catch (RemoteException ex) { Slog.w(TAG, "Unable to send window token to dream:" + ex); } } @Override public void onServiceDisconnected(ComponentName name) { if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream); mCurrentDream = null; mCurrentDreamToken = null; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Dreamland:"); pw.print(" component="); pw.println(mCurrentDreamComponent); pw.print(" token="); pw.println(mCurrentDreamToken); pw.print(" dream="); pw.println(mCurrentDream); } public void systemReady() { if (DEBUG) Slog.v(TAG, "ready to dream!"); } } core/java/android/service/dreams/IDreamManager.aidl 0 → 100644 +30 −0 Original line number Diff line number Diff line /** * Copyright (c) 2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.dreams; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.content.ComponentName; /** @hide */ interface IDreamManager { void dream(); void awaken(); void setDreamComponent(in ComponentName componentName); ComponentName getDreamComponent(); void testDream(in ComponentName componentName); } No newline at end of file core/java/android/service/dreams/IDreamService.aidl 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.dreams; /** * @hide */ oneway interface IDreamService { void attach(IBinder windowToken); } Loading
Android.mk +2 −0 Original line number Diff line number Diff line Loading @@ -132,6 +132,8 @@ LOCAL_SRC_FILES += \ core/java/android/os/IRemoteCallback.aidl \ core/java/android/os/IUpdateLock.aidl \ core/java/android/os/IVibratorService.aidl \ core/java/android/service/dreams/IDreamManager.aidl \ core/java/android/service/dreams/IDreamService.aidl \ core/java/android/service/wallpaper/IWallpaperConnection.aidl \ core/java/android/service/wallpaper/IWallpaperEngine.aidl \ core/java/android/service/wallpaper/IWallpaperService.aidl \ Loading
core/java/android/service/dreams/Dream.java 0 → 100644 +392 −0 Original line number Diff line number Diff line /** * */ package android.service.dreams; import com.android.internal.policy.PolicyManager; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.app.Service; import android.content.Context; import android.content.Intent; import android.content.pm.ActivityInfo; import android.graphics.drawable.ColorDrawable; import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.view.ActionMode; import android.view.IWindowManager; import android.view.KeyEvent; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager.LayoutParams; import android.view.accessibility.AccessibilityEvent; import android.view.WindowManager; import android.view.WindowManagerImpl; /** * @hide * */ public class Dream extends Service implements Window.Callback { private final static boolean DEBUG = true; private final static String TAG = "Dream"; /** * The {@link Intent} that must be declared as handled by the service. * To be supported, the service must also require the * {@link android.Manifest.permission#BIND_WALLPAPER} permission so * that other applications can not abuse it. */ @SdkConstant(SdkConstantType.SERVICE_ACTION) public static final String SERVICE_INTERFACE = "android.service.dreams.Dream"; private Window mWindow; private WindowManager mWindowManager; private IDreamManager mSandman; private boolean mInteractive; final Handler mHandler = new Handler(); boolean mFinished = false; // begin Window.Callback methods @Override public boolean dispatchKeyEvent(KeyEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchKeyEvent(event); } @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchKeyShortcutEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchTouchEvent(event); } @Override public boolean dispatchTrackballEvent(MotionEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchTrackballEvent(event); } @Override public boolean dispatchGenericMotionEvent(MotionEvent event) { if (!mInteractive) { finish(); return true; } return mWindow.superDispatchGenericMotionEvent(event); } @Override public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) { return false; } @Override public View onCreatePanelView(int featureId) { return null; } @Override public boolean onCreatePanelMenu(int featureId, Menu menu) { return false; } @Override public boolean onPreparePanel(int featureId, View view, Menu menu) { return false; } @Override public boolean onMenuOpened(int featureId, Menu menu) { return false; } @Override public boolean onMenuItemSelected(int featureId, MenuItem item) { return false; } @Override public void onWindowAttributesChanged(LayoutParams attrs) { } @Override public void onContentChanged() { } @Override public void onWindowFocusChanged(boolean hasFocus) { } @Override public void onAttachedToWindow() { mWindow.addFlags( WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED ); lightsOut(); } @Override public void onDetachedFromWindow() { } @Override public void onPanelClosed(int featureId, Menu menu) { } @Override public boolean onSearchRequested() { return false; } @Override public ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback callback) { return null; } @Override public void onActionModeStarted(ActionMode mode) { } @Override public void onActionModeFinished(ActionMode mode) { } // end Window.Callback methods public WindowManager getWindowManager() { return mWindowManager; } public Window getWindow() { return mWindow; } /** * Called when this Dream is constructed. Place your initialization here. * * Subclasses must call through to the superclass implementation. */ @Override public void onCreate() { super.onCreate(); if (DEBUG) Slog.v(TAG, "Dream created on thread " + Thread.currentThread().getId()); mSandman = IDreamManager.Stub.asInterface(ServiceManager.getService("dreams")); } /** * Called when this Dream is started. Place your initialization here. * * Subclasses must call through to the superclass implementation. * * XXX(dsandler) Might want to make this final and have a different method for clients to override */ @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } /** * Inflate a layout resource and set it to be the content view for this Dream. * Behaves similarly to {@link android.app.Activity#setContentView(int)}. * * @param layoutResID Resource ID to be inflated. * * @see #setContentView(android.view.View) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); } /** * Set a view to be the content view for this Dream. * Behaves similarly to {@link android.app.Activity#setContentView(android.view.View)}, * including using {@link ViewGroup.LayoutParams#MATCH_PARENT} as the layout height and width of the view. * * @param view The desired content to display. * * @see #setContentView(int) * @see #setContentView(android.view.View, android.view.ViewGroup.LayoutParams) */ public void setContentView(View view) { getWindow().setContentView(view); } /** * Set a view to be the content view for this Dream. * Behaves similarly to * {@link android.app.Activity#setContentView(android.view.View, android.view.ViewGroup.LayoutParams)}. * * @param view The desired content to display. * @param params Layout parameters for the view. * * @see #setContentView(android.view.View) * @see #setContentView(int) */ public void setContentView(View view, ViewGroup.LayoutParams params) { getWindow().setContentView(view, params); } /** * Add a view to the Dream's window, leaving other content views in place. * * @param view The desired content to display. * @param params Layout parameters for the view. */ public void addContentView(View view, ViewGroup.LayoutParams params) { getWindow().addContentView(view, params); } /** * @param mInteractive the mInteractive to set */ public void setInteractive(boolean mInteractive) { this.mInteractive = mInteractive; } /** * @return the mInteractive */ public boolean isInteractive() { return mInteractive; } /** Convenience method for setting View.SYSTEM_UI_FLAG_LOW_PROFILE on the content view. */ protected void lightsOut() { // turn the lights down low final View v = mWindow.getDecorView(); if (v != null) { v.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); } } /** * Finds a view that was identified by the id attribute from the XML that * was processed in {@link #onCreate}. * * @return The view if found or null otherwise. */ public View findViewById(int id) { return getWindow().findViewById(id); } /** * Called when this Dream is being removed from the screen and stopped. */ @Override public void onDestroy() { super.onDestroy(); mWindowManager.removeView(mWindow.getDecorView()); } /** * Creates a new dream window, attaches the current content view, and shows it. * * @param windowToken Binder to attach to the window to allow access to the correct window type. * @hide */ final /*package*/ void attach(IBinder windowToken) { if (DEBUG) Slog.v(TAG, "Dream attached on thread " + Thread.currentThread().getId()); mWindow = PolicyManager.makeNewWindow(this); mWindow.setCallback(this); mWindow.requestFeature(Window.FEATURE_NO_TITLE); mWindow.setBackgroundDrawable(new ColorDrawable(0xFF000000)); if (DEBUG) Slog.v(TAG, "attaching window token: " + windowToken + " to window of type " + WindowManager.LayoutParams.TYPE_DREAM); WindowManager.LayoutParams lp = mWindow.getAttributes(); lp.type = WindowManager.LayoutParams.TYPE_DREAM; lp.token = windowToken; lp.windowAnimations = com.android.internal.R.style.Animation_Dream; //WindowManagerImpl.getDefault().addView(mWindow.getDecorView(), lp); if (DEBUG) Slog.v(TAG, "created and attached window: " + mWindow); mWindow.setWindowManager(null, windowToken, "dream", true); mWindowManager = mWindow.getWindowManager(); // now make it visible mHandler.post(new Runnable(){ @Override public void run() { if (DEBUG) Slog.v(TAG, "Dream window added on thread " + Thread.currentThread().getId()); getWindowManager().addView(mWindow.getDecorView(), mWindow.getAttributes()); }}); } /** * Stop the dream and wake up. * * After this method is called, the service will be stopped. */ public void finish() { if (mFinished) return; try { mSandman.awaken(); // assuming we were started by the DreamManager stopSelf(); // if launched via any other means mFinished = true; } catch (RemoteException ex) { // sigh } } class IDreamServiceWrapper extends IDreamService.Stub { public IDreamServiceWrapper() { } public void attach(IBinder windowToken) { Dream.this.attach(windowToken); } } /** * Implement to return the implementation of the internal accessibility * service interface. Subclasses should not override. */ @Override public final IBinder onBind(Intent intent) { return new IDreamServiceWrapper(); } }
core/java/android/service/dreams/DreamManagerService.java 0 → 100644 +182 −0 Original line number Diff line number Diff line package android.service.dreams; import static android.provider.Settings.Secure.SCREENSAVER_COMPONENT; import java.io.FileDescriptor; import java.io.PrintWriter; import com.android.internal.view.IInputMethod; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.os.Binder; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.provider.Settings; import android.util.Log; import android.util.Slog; import android.view.IWindowManager; import android.view.WindowManager; /** * * @hide * */ public class DreamManagerService extends IDreamManager.Stub implements ServiceConnection { private static final boolean DEBUG = true; private static final String TAG = "DreamManagerService"; final Object mLock = new Object[0]; private Context mContext; private IWindowManager mIWindowManager; private ComponentName mCurrentDreamComponent; private IDreamService mCurrentDream; private Binder mCurrentDreamToken; public DreamManagerService(Context context) { if (DEBUG) Slog.v(TAG, "DreamManagerService startup"); mContext = context; mIWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); } private void checkPermission(String permission) { if (PackageManager.PERMISSION_GRANTED != mContext.checkCallingOrSelfPermission(permission)) { throw new SecurityException("Access denied to process: " + Binder.getCallingPid() + ", must have permission " + permission); } } // IDreamManager method public void dream() { ComponentName name = getDreamComponent(); if (name != null) { synchronized (mLock) { final long ident = Binder.clearCallingIdentity(); try { bindDreamComponentL(name, false); } finally { Binder.restoreCallingIdentity(ident); } } } } // IDreamManager method public void setDreamComponent(ComponentName name) { Settings.Secure.putString(mContext.getContentResolver(), SCREENSAVER_COMPONENT, name.flattenToString()); } // IDreamManager method public ComponentName getDreamComponent() { // TODO(dsandler) don't load this every time, watch the value String component = Settings.Secure.getString(mContext.getContentResolver(), SCREENSAVER_COMPONENT); if (component == null) { component = mContext.getResources().getString( com.android.internal.R.string.config_defaultDreamComponent); } if (component != null) { return ComponentName.unflattenFromString(component); } else { return null; } } // IDreamManager method public void testDream(ComponentName name) { if (DEBUG) Slog.v(TAG, "startDream name=" + name + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); // checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); synchronized (mLock) { final long ident = Binder.clearCallingIdentity(); try { bindDreamComponentL(name, true); } finally { Binder.restoreCallingIdentity(ident); } } } // IDreamManager method public void awaken() { if (DEBUG) Slog.v(TAG, "awaken()"); synchronized (mLock) { if (mCurrentDream != null) { mContext.unbindService(this); } } } public void bindDreamComponentL(ComponentName componentName, boolean test) { if (DEBUG) Slog.v(TAG, "bindDreamComponent: componentName=" + componentName + " pid=" + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()); Intent intent = new Intent(Intent.ACTION_MAIN) .setComponent(componentName) .addFlags( Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS ) .putExtra("android.dreams.TEST", test); if (!mContext.bindService(intent, this, Context.BIND_AUTO_CREATE)) { Slog.w(TAG, "unable to bind service: " + componentName); return; } mCurrentDreamComponent = componentName; mCurrentDreamToken = new Binder(); try { if (DEBUG) Slog.v(TAG, "Adding window token: " + mCurrentDreamToken + " for window type: " + WindowManager.LayoutParams.TYPE_DREAM); mIWindowManager.addWindowToken(mCurrentDreamToken, WindowManager.LayoutParams.TYPE_DREAM); } catch (RemoteException e) { Slog.w(TAG, "Unable to add window token. Proceed at your own risk."); } } @Override public void onServiceConnected(ComponentName name, IBinder service) { if (DEBUG) Slog.v(TAG, "connected to dream: " + name + " binder=" + service + " thread=" + Thread.currentThread().getId()); mCurrentDream = IDreamService.Stub.asInterface(service); try { if (DEBUG) Slog.v(TAG, "attaching with token:" + mCurrentDreamToken); mCurrentDream.attach(mCurrentDreamToken); } catch (RemoteException ex) { Slog.w(TAG, "Unable to send window token to dream:" + ex); } } @Override public void onServiceDisconnected(ComponentName name) { if (DEBUG) Slog.v(TAG, "disconnected: " + name + " service: " + mCurrentDream); mCurrentDream = null; mCurrentDreamToken = null; } @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { pw.println("Dreamland:"); pw.print(" component="); pw.println(mCurrentDreamComponent); pw.print(" token="); pw.println(mCurrentDreamToken); pw.print(" dream="); pw.println(mCurrentDream); } public void systemReady() { if (DEBUG) Slog.v(TAG, "ready to dream!"); } }
core/java/android/service/dreams/IDreamManager.aidl 0 → 100644 +30 −0 Original line number Diff line number Diff line /** * Copyright (c) 2012, The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.dreams; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.content.ComponentName; /** @hide */ interface IDreamManager { void dream(); void awaken(); void setDreamComponent(in ComponentName componentName); ComponentName getDreamComponent(); void testDream(in ComponentName componentName); } No newline at end of file
core/java/android/service/dreams/IDreamService.aidl 0 → 100644 +24 −0 Original line number Diff line number Diff line /* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.service.dreams; /** * @hide */ oneway interface IDreamService { void attach(IBinder windowToken); }