diff options
author | Jim Miller <jaggies@google.com> | 2013-03-22 16:11:08 -0700 |
---|---|---|
committer | Jim Miller <jaggies@google.com> | 2013-04-26 14:34:21 -0700 |
commit | c0b676dcc23baedb12946c3470d9fa9b02cb39e0 (patch) | |
tree | a0050fe524ddbbdd56bd81ea7c67b3a7dd248c69 | |
parent | 69fd7bd660a3a2d1b4c260eee9bbc6868b47d0c4 (diff) | |
download | frameworks_base-c0b676dcc23baedb12946c3470d9fa9b02cb39e0.zip frameworks_base-c0b676dcc23baedb12946c3470d9fa9b02cb39e0.tar.gz frameworks_base-c0b676dcc23baedb12946c3470d9fa9b02cb39e0.tar.bz2 |
Add keyguard background scrim and protection around keyguard APIs
With this change, the system process will put up a scrim in the
event keyguard crashes to protect underlying content.
It also adds permission checks to prevent unathorized access
through the binder APIs.
Cleaned up KeyguardTestActivity to build separately.
Removed unused resources.
Change-Id: I9e370c6bfb7dca68eae9eae304c815fb84a753d2
17 files changed, 196 insertions, 31 deletions
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 2ab981b..83d6061 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2209,6 +2209,13 @@ android:label="@string/permlab_access_keyguard_secure_storage" android:description="@string/permdesc_access_keyguard_secure_storage" /> + <!-- Allows an application to control keyguard. Only allowed for system processes. + @hide --> + <permission android:name="android.permission.CONTROL_KEYGUARD" + android:protectionLevel="signature" + android:label="@string/permlab_control_keyguard" + android:description="@string/permdesc_control_keyguard" /> + <!-- Must be required by an {@link android.service.notification.NotificationListenerService}, to ensure that only the system can bind to it. --> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index b832bbe..09be719 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3474,6 +3474,11 @@ <!-- Description of an application permission that lets an application access keyguard secure storage. --> <string name="permdesc_access_keyguard_secure_storage">Allows an application to access keguard secure storage.</string> + <!-- Title of an application permission that lets it control keyguard. --> + <string name="permlab_control_keyguard">Control displaying and hiding keyguard</string> + <!-- Description of an application permission that lets it control keyguard. --> + <string name="permdesc_control_keyguard">Allows an application to control keguard.</string> + <!-- Shown in the tutorial for tap twice for zoom control. --> <string name="tutorial_double_tap_to_zoom_message_short">Touch twice for zoom control</string> diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk index 2f8edad..bc86a44 100644 --- a/packages/Keyguard/Android.mk +++ b/packages/Keyguard/Android.mk @@ -16,7 +16,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_SRC_FILES := $(call all-subdir-java-files) $(call all-subdir-Iaidl-files) +LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) LOCAL_JAVA_LIBRARIES := services @@ -28,4 +28,4 @@ LOCAL_PROGUARD_FLAG_FILES := proguard.flags include $(BUILD_PACKAGE) -include $(call all-makefiles-under,$(LOCAL_PATH)) +#include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml index 38e764a..7a40a9e 100644 --- a/packages/Keyguard/AndroidManifest.xml +++ b/packages/Keyguard/AndroidManifest.xml @@ -38,7 +38,7 @@ <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" /> <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> - <application android:label="@string/app_name" android:icon="@drawable/app_icon" + <application android:label="@string/app_name" android:process="com.android.systemui.keyguard" android:persistent="true" > diff --git a/packages/Keyguard/res/drawable-nodpi/app_icon.png b/packages/Keyguard/res/drawable-nodpi/app_icon.png Binary files differdeleted file mode 100644 index ea31bd8..0000000 --- a/packages/Keyguard/res/drawable-nodpi/app_icon.png +++ /dev/null diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java index 9fa4790..f89ad65 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardService.java @@ -21,7 +21,11 @@ import java.io.PrintWriter; import android.app.Service; import android.content.Intent; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +import android.os.Binder; import android.os.Bundle; +import android.os.Debug; import android.os.IBinder; import android.util.Log; @@ -32,6 +36,7 @@ import com.android.internal.widget.LockPatternUtils; public class KeyguardService extends Service { static final String TAG = "KeyguardService"; + static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD; private KeyguardViewMediator mKeyguardViewMediator; @Override @@ -53,6 +58,14 @@ public class KeyguardService extends Service { // TODO } + void checkPermission() { + if (getBaseContext().checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) { + Log.w(TAG, "Caller needs permission '" + PERMISSION + "' to call " + Debug.getCaller()); + throw new SecurityException("Access denied to process: " + Binder.getCallingPid() + + ", must have permission " + PERMISSION); + } + } + private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() { public boolean isShowing() { return mKeyguardViewMediator.isShowing(); @@ -70,48 +83,61 @@ public class KeyguardService extends Service { mKeyguardViewMediator.verifyUnlock(callback); } public void keyguardDone(boolean authenticated, boolean wakeup) { + checkPermission(); mKeyguardViewMediator.keyguardDone(authenticated, wakeup); } public void setHidden(boolean isHidden) { + checkPermission(); mKeyguardViewMediator.setHidden(isHidden); } public void dismiss() { mKeyguardViewMediator.dismiss(); } public void onWakeKeyWhenKeyguardShowing(int keyCode) { + checkPermission(); mKeyguardViewMediator.onWakeKeyWhenKeyguardShowing(keyCode); } public void onWakeMotionWhenKeyguardShowing() { + checkPermission(); mKeyguardViewMediator.onWakeMotionWhenKeyguardShowing(); } public void onDreamingStarted() { + checkPermission(); mKeyguardViewMediator.onDreamingStarted(); } public void onDreamingStopped() { + checkPermission(); mKeyguardViewMediator.onDreamingStopped(); } public void onScreenTurnedOff(int reason) { + checkPermission(); mKeyguardViewMediator.onScreenTurnedOff(reason); } public void onScreenTurnedOn(IKeyguardShowCallback callback) { + checkPermission(); mKeyguardViewMediator.onScreenTurnedOn(callback); } public void setKeyguardEnabled(boolean enabled) { + checkPermission(); mKeyguardViewMediator.setKeyguardEnabled(enabled); } public boolean isDismissable() { return mKeyguardViewMediator.isDismissable(); } public void onSystemReady() { + checkPermission(); mKeyguardViewMediator.onSystemReady(); } public void doKeyguardTimeout(Bundle options) { + checkPermission(); mKeyguardViewMediator.doKeyguardTimeout(options); } public void setCurrentUser(int userId) { + checkPermission(); mKeyguardViewMediator.setCurrentUser(userId); } public void showAssistant() { + checkPermission(); mKeyguardViewMediator.showAssistant(); } }; diff --git a/packages/Keyguard/test/Android.mk b/packages/Keyguard/test/Android.mk new file mode 100644 index 0000000..d011df4 --- /dev/null +++ b/packages/Keyguard/test/Android.mk @@ -0,0 +1,28 @@ +# Copyright (C) 2013 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. +# + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := $(call all-java-files-under, src) + +LOCAL_PACKAGE_NAME := KeyguardTest + +# Remove this to verify permission checks are working correctly +LOCAL_CERTIFICATE := platform + +# LOCAL_PROGUARD_FLAG_FILES := proguard.flags + +include $(BUILD_PACKAGE) diff --git a/packages/Keyguard/test/AndroidManifest.xml b/packages/Keyguard/test/AndroidManifest.xml new file mode 100644 index 0000000..b801e4b --- /dev/null +++ b/packages/Keyguard/test/AndroidManifest.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 2013, 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. +*/ +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.android.keyguard.test"> + <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/> + <uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> + <application android:label="@string/app_name" android:icon="@drawable/app_icon"> + <activity android:name=".KeyguardTestActivity" + android:label="@string/app_name" + android:theme="@android:style/Theme.Holo"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + </application> +</manifest> diff --git a/packages/Keyguard/test/res/drawable-hdpi/app_icon.png b/packages/Keyguard/test/res/drawable-hdpi/app_icon.png Binary files differnew file mode 100644 index 0000000..732133c --- /dev/null +++ b/packages/Keyguard/test/res/drawable-hdpi/app_icon.png diff --git a/packages/Keyguard/test/res/drawable-mdpi/app_icon.png b/packages/Keyguard/test/res/drawable-mdpi/app_icon.png Binary files differnew file mode 100644 index 0000000..30eb974 --- /dev/null +++ b/packages/Keyguard/test/res/drawable-mdpi/app_icon.png diff --git a/packages/Keyguard/test/res/drawable-xhdpi/app_icon.png b/packages/Keyguard/test/res/drawable-xhdpi/app_icon.png Binary files differnew file mode 100644 index 0000000..c44a330 --- /dev/null +++ b/packages/Keyguard/test/res/drawable-xhdpi/app_icon.png diff --git a/packages/Keyguard/res/layout/keyguard_test_activity.xml b/packages/Keyguard/test/res/layout/keyguard_test_activity.xml index a3b75b0..dab1088 100644 --- a/packages/Keyguard/res/layout/keyguard_test_activity.xml +++ b/packages/Keyguard/test/res/layout/keyguard_test_activity.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ** -** Copyright 2012, The Android Open Source Project +** Copyright 2013, 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. diff --git a/packages/Keyguard/res/menu/optionmenu.xml b/packages/Keyguard/test/res/menu/optionmenu.xml index 22f300d..22f300d 100644 --- a/packages/Keyguard/res/menu/optionmenu.xml +++ b/packages/Keyguard/test/res/menu/optionmenu.xml diff --git a/packages/Keyguard/res/values/activitystrings.xml b/packages/Keyguard/test/res/values/strings.xml index 5af9dea..129204b 100644 --- a/packages/Keyguard/res/values/activitystrings.xml +++ b/packages/Keyguard/test/res/values/strings.xml @@ -2,7 +2,7 @@ <!-- /* //device/apps/common/assets/res/any/strings.xml ** -** Copyright 2006, The Android Open Source Project +** Copyright 2013, 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. diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTestActivity.java b/packages/Keyguard/test/src/com/android/keyguard/test/KeyguardTestActivity.java index 0ff00e3..e89c10e 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardTestActivity.java +++ b/packages/Keyguard/test/src/com/android/keyguard/test/KeyguardTestActivity.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.keyguard; +package com.android.keyguard.test; import com.android.internal.policy.IKeyguardShowCallback; import com.android.internal.policy.IKeyguardExitCallback; @@ -28,6 +28,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.SystemClock; @@ -56,6 +57,7 @@ public class KeyguardTestActivity extends Activity implements OnClickListener { private static final int MODE_SIM_PIN = 4; private static final int MODE_SIM_PUK = 5; private static final String SECURITY_MODE = "security_mode"; + Handler mHandler = new Handler(); IKeyguardService mService = null; @@ -76,13 +78,17 @@ public class KeyguardTestActivity extends Activity implements OnClickListener { class KeyguardExitCallback extends IKeyguardExitCallback.Stub { @Override - public void onKeyguardExitResult(boolean success) throws RemoteException { - new AlertDialog.Builder(KeyguardTestActivity.this) - .setMessage("Result: " + success) - .setPositiveButton("OK", null) - .show(); + public void onKeyguardExitResult(final boolean success) throws RemoteException { + mHandler.post(new Runnable() { + @Override + public void run() { + new AlertDialog.Builder(KeyguardTestActivity.this) + .setMessage("Result: " + success) + .setPositiveButton("OK", null) + .show(); + } + }); } - }; private class RemoteServiceConnection implements ServiceConnection { @@ -158,12 +164,13 @@ public class KeyguardTestActivity extends Activity implements OnClickListener { setMode(savedInstanceState.getInt(SECURITY_MODE)); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.optionmenu, menu); - return true; - } +// TODO: Find a secure way to inject mock into keyguard... +// @Override +// public boolean onCreateOptionsMenu(Menu menu) { +// MenuInflater inflater = getMenuInflater(); +// inflater.inflate(R.menu.optionmenu, menu); +// return true; +// } private void setMode(int mode) { mTestSimPin = false; @@ -255,12 +262,22 @@ public class KeyguardTestActivity extends Activity implements OnClickListener { mService.doKeyguardTimeout(null); break; case R.id.verify_unlock: - mService.verifyUnlock(mKeyguardExitCallback); + mService.doKeyguardTimeout(null); + // Wait for keyguard to lock and then try this... + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + try { + mService.verifyUnlock(mKeyguardExitCallback); + } catch (RemoteException e) { + Log.e(TAG, "Failed verifyUnlock()", e); + } + } + }, 5000); break; } } catch (RemoteException e) { - Log.e(TAG, "Remote service died"); - e.printStackTrace(); + Log.e(TAG, "onClick(): Failed due to remote exeption", e); } } diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java index 63584ac..41efaa5 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java @@ -1722,7 +1722,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; } mKeyguard = win; - hideKeyguardScrim(); break; case TYPE_KEYGUARD_SCRIM: if (mKeyguardScrim != null) { @@ -1742,7 +1741,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } else if (mKeyguard == win) { Log.v(TAG, "Removing keyguard window (Did it crash?)"); mKeyguard = null; - showKeyguardScrimLw(); + mKeyguardDelegate.showScrim(); } else if (mKeyguardScrim == win) { Log.v(TAG, "Removing keyguard scrim"); mKeyguardScrim = null; @@ -1751,14 +1750,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } - private void showKeyguardScrimLw() { - Log.v(TAG, "*** SHOWING KEYGUARD SCRIM ***"); - } - - private void hideKeyguardScrim() { - Log.v(TAG, "*** HIDING KEYGUARD SCRIM ***"); - } - static final boolean PRINT_ANIM = false; /** {@inheritDoc} */ diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java index bf18b99..2bb94be 100644 --- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java +++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java @@ -4,12 +4,17 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; +import android.content.pm.ActivityInfo; +import android.graphics.PixelFormat; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.UserHandle; import android.util.Log; import android.util.Slog; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; import android.view.WindowManagerPolicy.OnKeyguardExitResult; import com.android.internal.policy.IKeyguardExitCallback; @@ -29,6 +34,7 @@ public class KeyguardServiceDelegate { private static final String TAG = "KeyguardServiceDelegate"; private static final boolean DEBUG = true; protected KeyguardServiceWrapper mKeyguardService; + private View mScrim; // shown if keyguard crashes private KeyguardState mKeyguardState = new KeyguardState(); /* package */ static final class KeyguardState { @@ -64,6 +70,7 @@ public class KeyguardServiceDelegate { if (mShowListener != null) { mShowListener.onShown(windowToken); } + hideScrim(); } }; @@ -87,6 +94,7 @@ public class KeyguardServiceDelegate { public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) { Intent intent = new Intent(); intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS); + mScrim = createScrim(context); if (!context.bindServiceAsUser(intent, mKeyguardConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) { if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS); @@ -102,7 +110,10 @@ public class KeyguardServiceDelegate { mKeyguardService = new KeyguardServiceWrapper( IKeyguardService.Stub.asInterface(service)); if (mKeyguardState.systemIsReady) { + // If the system is ready, it means keyguard crashed and restarted. mKeyguardService.onSystemReady(); + // This is used to hide the scrim once keyguard displays. + mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null)); } } @@ -257,4 +268,51 @@ public class KeyguardServiceDelegate { mKeyguardState.currentUser = newUserId; } + private static final View createScrim(Context context) { + View view = new View(context); + + int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN + | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR + | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN + | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER + ; + + final int stretch = ViewGroup.LayoutParams.MATCH_PARENT; + final int type = WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM; + WindowManager.LayoutParams lp = new WindowManager.LayoutParams( + stretch, stretch, type, flags, PixelFormat.TRANSLUCENT); + lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE; + lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; + lp.setTitle("KeyguardScrim"); + WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); + wm.addView(view, lp); + view.setVisibility(View.GONE); + // Disable pretty much everything in statusbar until keyguard comes back and we know + // the state of the world. + view.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME + | View.STATUS_BAR_DISABLE_BACK + | View.STATUS_BAR_DISABLE_RECENT + | View.STATUS_BAR_DISABLE_EXPAND + | View.STATUS_BAR_DISABLE_SEARCH); + return view; + } + + public void showScrim() { + mScrim.post(new Runnable() { + @Override + public void run() { + mScrim.setVisibility(View.VISIBLE); + } + }); + } + + public void hideScrim() { + mScrim.post(new Runnable() { + @Override + public void run() { + mScrim.setVisibility(View.GONE); + } + }); + } + } |