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:
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -265,4 +265,8 @@ public class KeyguardWidgetFrame extends FrameLayout {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void onActive(boolean isActive) {
|
||||
// hook for subclasses
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user