am 86b6357e: Manual f/b merge of lockhotness camera integration.

* commit '86b6357e5eb91950eac7de7ffe29e5a4ad32903b':
  Manual f/b merge of lockhotness camera integration.
This commit is contained in:
John Spurlock
2012-10-29 12:45:17 -07:00
committed by Android Git Automerger
10 changed files with 312 additions and 37 deletions

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
**
** Copyright 2009, 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.
*/
-->
<!-- This is a view that shows general status information in Keyguard. -->
<com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/keyguard_camera_widget"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/camera_widget" />
</com.android.internal.policy.impl.keyguard.KeyguardWidgetFrame>

View File

@@ -19,4 +19,6 @@
<bool name="show_ongoing_ime_switcher">true</bool>
<bool name="kg_share_status_area">false</bool>
<bool name="kg_sim_puk_account_full_screen">false</bool>
<!-- No camera for you, tablet user -->
<bool name="kg_enable_camera_default_widget">false</bool>
</resources>

View File

@@ -15,6 +15,7 @@
-->
<resources>
<bool name="kg_enable_camera_default_widget">true</bool>
<bool name="action_bar_embed_tabs">true</bool>
<bool name="action_bar_embed_tabs_pre_jb">false</bool>
<bool name="split_action_bar_is_narrow">true</bool>

View File

@@ -3935,6 +3935,14 @@
you will be asked to unlock your phone using an email account.\n\n
Try again in <xliff:g id="number">%d</xliff:g> seconds.
</string>
<!-- Placeholder text shown if the camera widget layout is missing or invalid -->
<string name="kg_camera_widget_not_found">Camera widget not found</string>
<!-- DO NOT TRANSLATE. Context package to use when locating the camera widget -->
<string name="kg_camera_widget_context_package">com.google.android.gallery3d</string>
<!-- DO NOT TRANSLATE. Layout package to use when locating the camera widget -->
<string name="kg_camera_widget_layout_package">com.android.gallery3d</string>
<!-- DO NOT TRANSLATE. Layout name to use when locating the camera widget -->
<string name="kg_camera_widget_layout_name">keyguard_widget</string>
<!-- Message shown in dialog when user is attempting to set the music volume above the
recommended maximum level for headphones -->

View File

@@ -1088,7 +1088,6 @@
<java-symbol type="layout" name="keyguard_multi_user_selector_widget" />
<java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
<java-symbol type="layout" name="keyguard_add_widget" />
<java-symbol type="layout" name="keyguard_camera_widget" />
<java-symbol type="anim" name="slide_in_child_bottom" />
<java-symbol type="anim" name="slide_in_right" />
@@ -1192,6 +1191,7 @@
<java-symbol type="bool" name="config_lidControlsSleep" />
<java-symbol type="bool" name="config_reverseDefaultRotation" />
<java-symbol type="bool" name="config_showNavigationBar" />
<java-symbol type="bool" name="kg_enable_camera_default_widget" />
<java-symbol type="bool" name="kg_share_status_area" />
<java-symbol type="bool" name="kg_sim_puk_account_full_screen" />
<java-symbol type="bool" name="target_honeycomb_needs_options_menu" />
@@ -1381,6 +1381,10 @@
<java-symbol type="string" name="keyguard_password_enter_pin_code" />
<java-symbol type="string" name="keyguard_password_enter_puk_code" />
<java-symbol type="string" name="keyguard_password_wrong_pin_code" />
<java-symbol type="string" name="kg_camera_widget_context_package" />
<java-symbol type="string" name="kg_camera_widget_layout_name" />
<java-symbol type="string" name="kg_camera_widget_layout_package" />
<java-symbol type="string" name="kg_camera_widget_not_found" />
<java-symbol type="string" name="lockscreen_carrier_default" />
<java-symbol type="string" name="lockscreen_charged" />
<java-symbol type="string" name="lockscreen_failed_attempts_almost_at_wipe" />

View File

@@ -0,0 +1,249 @@
/*
* 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 com.android.internal.policy.impl.keyguard;
import java.util.List;
import android.app.ActivityManagerNative;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.Color;
import android.os.Handler;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.TextView;
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
public class CameraWidgetFrame extends KeyguardWidgetFrame {
private static final String TAG = CameraWidgetFrame.class.getSimpleName();
private static final boolean DEBUG = KeyguardHostView.DEBUG;
interface Callbacks {
void onLaunchingCamera();
void onCameraLaunched();
}
private final Handler mHandler = new Handler();
private final LockPatternUtils mLockPatternUtils;
private final Callbacks mCallbacks;
private boolean mCameraWidgetFound;
private long mLaunchCameraStart;
private final Runnable mLaunchCameraRunnable = new Runnable() {
@Override
public void run() {
launchCamera();
}};
public CameraWidgetFrame(Context context, Callbacks callbacks) {
super(context);
mLockPatternUtils = new LockPatternUtils(context);
mCallbacks = callbacks;
View cameraView = createCameraView();
addView(cameraView);
}
private View createCameraView() {
View cameraView = null;
Exception exception = null;
try {
String contextPackage = mContext.getString(R.string.kg_camera_widget_context_package);
String layoutPackage = mContext.getString(R.string.kg_camera_widget_layout_package);
String layoutName = mContext.getString(R.string.kg_camera_widget_layout_name);
Context cameraContext = mContext.createPackageContext(
contextPackage, Context.CONTEXT_RESTRICTED);
LayoutInflater cameraInflater = (LayoutInflater)
cameraContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
cameraInflater = cameraInflater.cloneInContext(cameraContext);
int layoutId = cameraContext.getResources()
.getIdentifier(layoutName, "layout", layoutPackage);
cameraView = cameraInflater.inflate(layoutId, null, false);
} catch (NameNotFoundException e) {
exception = e;
} catch (RuntimeException e) {
exception = e;
}
if (exception != null) {
Log.w(TAG, "Error creating camera widget view", exception);
}
if (cameraView == null) {
cameraView = createCameraErrorView();
} else {
mCameraWidgetFound = true;
}
return cameraView;
}
private View createCameraErrorView() {
TextView errorView = new TextView(mContext);
errorView.setGravity(Gravity.CENTER);
errorView.setText(R.string.kg_camera_widget_not_found);
errorView.setBackgroundColor(Color.argb(127, 0, 0, 0));
return errorView;
}
private void transitionToCamera() {
animate()
.scaleX(1.22f) // TODO compute this at runtime
.scaleY(1.22f)
.setDuration(250)
.withEndAction(mLaunchCameraRunnable)
.start();
mCallbacks.onLaunchingCamera();
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (!mCameraWidgetFound) return;
if (!hasWindowFocus) {
if (mLaunchCameraStart > 0) {
long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
if (DEBUG) Log.d(TAG, String.format("Camera took %s to launch", launchTime));
mLaunchCameraStart = 0;
}
onCameraLaunched();
}
}
@Override
public void onActive(boolean isActive) {
if (!mCameraWidgetFound) return;
if (isActive) {
mHandler.post(new Runnable(){
@Override
public void run() {
transitionToCamera();
}});
} else {
reset();
}
}
private void onCameraLaunched() {
reset();
mCallbacks.onCameraLaunched();
}
private void reset() {
animate().cancel();
setScaleX(1);
setScaleY(1);
}
// =========== from KeyguardSelectorView ===========
protected void launchCamera() {
mLaunchCameraStart = SystemClock.uptimeMillis();
boolean isSecure = mLockPatternUtils.isSecure();
if (DEBUG) Log.d(TAG, "launchCamera " + (isSecure?"(secure)":"(insecure)"));
if (isSecure) {
// Launch the secure version of the camera
final Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE);
intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
if (wouldLaunchResolverActivity(intent)) {
// TODO: Show disambiguation dialog instead.
// For now, we'll treat this like launching any other app from secure keyguard.
// When they do, user sees the system's ResolverActivity which lets them choose
// which secure camera to use.
launchActivity(intent, false);
} else {
launchActivity(intent, true);
}
} else {
// Launch the normal camera
launchActivity(new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA), false);
}
}
/**
* Launches the said intent for the current foreground user.
* @param intent
* @param showsWhileLocked true if the activity can be run on top of keyguard.
* See {@link WindowManager#FLAG_SHOW_WHEN_LOCKED}
*/
private void launchActivity(final Intent intent, boolean showsWhileLocked) {
intent.addFlags(
Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_SINGLE_TOP
| Intent.FLAG_ACTIVITY_CLEAR_TOP);
boolean isSecure = mLockPatternUtils.isSecure();
if (!isSecure || showsWhileLocked) {
if (!isSecure) try {
ActivityManagerNative.getDefault().dismissKeyguardOnNextActivity();
} catch (RemoteException e) {
Log.w(TAG, "can't dismiss keyguard on launch");
}
try {
mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
} catch (ActivityNotFoundException e) {
Log.w(TAG, "Activity not found for intent + " + intent.getAction());
}
} else {
Log.w(TAG, "TODO: handle this case");
onCameraLaunched();
// // Create a runnable to start the activity and ask the user to enter their
// // credentials.
// mCallback.setOnDismissRunnable(new Runnable() {
// @Override
// public void run() {
// mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
// }
// });
// mCallback.dismiss(false);
}
}
private boolean wouldLaunchResolverActivity(Intent intent) {
PackageManager packageManager = mContext.getPackageManager();
ResolveInfo resolved = packageManager.resolveActivityAsUser(intent,
PackageManager.MATCH_DEFAULT_ONLY, mLockPatternUtils.getCurrentUser());
final List<ResolveInfo> appList = packageManager.queryIntentActivitiesAsUser(
intent, PackageManager.MATCH_DEFAULT_ONLY, mLockPatternUtils.getCurrentUser());
// If the list contains the above resolved activity, then it can't be
// ResolverActivity itself.
for (int i = 0; i < appList.size(); i++) {
ResolveInfo tmp = appList.get(i);
if (tmp.activityInfo.name.equals(resolved.activityInfo.name)
&& tmp.activityInfo.packageName.equals(resolved.activityInfo.packageName)) {
return false;
}
}
return true;
}
}

View File

@@ -834,8 +834,32 @@ public class KeyguardHostView extends KeyguardViewBase {
mAppWidgetContainer.addWidget(addWidget);
View statusWidget = inflater.inflate(R.layout.keyguard_status_view, null, true);
mAppWidgetContainer.addWidget(statusWidget);
View cameraWidget = inflater.inflate(R.layout.keyguard_camera_widget, null, true);
mAppWidgetContainer.addWidget(cameraWidget);
if (mContext.getResources().getBoolean(R.bool.kg_enable_camera_default_widget)) {
View cameraWidget = new CameraWidgetFrame(mContext, new CameraWidgetFrame.Callbacks() {
private SlidingChallengeLayout locateSlider() {
return (SlidingChallengeLayout) findViewById(R.id.sliding_layout);
}
@Override
public void onLaunchingCamera() {
SlidingChallengeLayout slider = locateSlider();
if (slider != null) {
slider.showHandle(false);
}
}
@Override
public void onCameraLaunched() {
SlidingChallengeLayout slider = locateSlider();
if (slider != null) {
slider.showHandle(true);
}
mAppWidgetContainer.scrollLeft();
}
});
mAppWidgetContainer.addWidget(cameraWidget);
}
View addWidgetButton = addWidget.findViewById(R.id.keyguard_add_widget_view);
addWidgetButton.setOnClickListener(new OnClickListener() {

View File

@@ -265,4 +265,8 @@ public class KeyguardWidgetFrame extends FrameLayout {
invalidate();
}
}
public void onActive(boolean isActive) {
// hook for subclasses
}
}

View File

@@ -98,11 +98,20 @@ public class KeyguardWidgetPager extends PagedView implements PagedView.PageSwit
// Extend the display timeout if the user switches pages
if (mPage != newPageIndex) {
int oldPageIndex = mPage;
mPage = newPageIndex;
if (mCallbacks != null) {
mCallbacks.onUserActivityTimeoutChanged();
mCallbacks.userActivity();
}
KeyguardWidgetFrame oldWidgetPage = getWidgetPageAt(oldPageIndex);
if (oldWidgetPage != null) {
oldWidgetPage.onActive(false);
}
KeyguardWidgetFrame newWidgetPage = getWidgetPageAt(newPageIndex);
if (newWidgetPage != null) {
newWidgetPage.onActive(true);
}
}
if (mViewStateManager != null) {
mViewStateManager.onPageSwitch(newPage, newPageIndex);

View File

@@ -42,6 +42,7 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
// Drawn to show the drag handle in closed state; crossfades to the challenge view
// when challenge is fully visible
private Drawable mHandleDrawable;
private boolean mShowHandle = true;
// Initialized during measurement from child layoutparams
private View mChallengeView;
@@ -556,7 +557,8 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
@Override
public void draw(Canvas c) {
super.draw(c);
if (mChallengeOffset < 1.f && mChallengeView != null && mHandleDrawable != null) {
if (mChallengeOffset < 1.f
&& mChallengeView != null && mHandleDrawable != null && mShowHandle) {
final int top = mChallengeView.getTop();
mHandleDrawable.setBounds(0, top, getWidth(), top + mDragHandleSize);
final float alpha = sHandleFadeInterpolator.getInterpolation(1 - mChallengeOffset);
@@ -661,6 +663,11 @@ public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout
showChallenge(true);
}
public void showHandle(boolean show) {
mShowHandle = show;
invalidate();
}
@Override
public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);