Commit 0dc03860 authored by Amit Kumar's avatar Amit Kumar 💻
Browse files

Add recent tasks related stuff

parent 8e3241f7
Pipeline #123767 failed with stage
in 2 minutes and 1 second
......@@ -102,11 +102,10 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
implementation "androidx.dynamicanimation:dynamicanimation:1.0.0"
implementation files('libs/sysui_shared.jar')
apiNougatImplementation 'org.cyanogenmod:platform.sdk:6.0'
apiOreoImplementation files('libs/lineage-sdk-oreo.jar')
implementation files('libs/sysui_shared.jar')
debugImplementation 'com.amitshekhar.android:debug-db:1.0.4'
......
......@@ -26,6 +26,7 @@ import android.view.ViewGroup;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
......@@ -378,4 +379,23 @@ public class Utilities {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
return powerManager.isPowerSaveMode();
}
public static <T> T getOverrideObject(Class<T> clazz, Context context, int resId) {
String className = context.getString(resId);
if (!TextUtils.isEmpty(className)) {
try {
Class<?> cls = Class.forName(className);
return (T) cls.getDeclaredConstructor(Context.class).newInstance(context);
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException
| ClassCastException | NoSuchMethodException | InvocationTargetException e) {
Log.e(TAG, "Bad overriden class", e);
}
}
try {
return clazz.newInstance();
} catch (InstantiationException|IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
/*
* Copyright (C) 2016 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 foundation.e.blisslauncher.core.utils;
import android.app.AppOpsManager;
import android.content.ActivityNotFoundException;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import java.net.URISyntaxException;
import java.util.List;
import foundation.e.blisslauncher.R;
import foundation.e.blisslauncher.core.Utilities;
import foundation.e.blisslauncher.core.database.model.ApplicationItem;
import foundation.e.blisslauncher.core.database.model.LauncherItem;
import foundation.e.blisslauncher.core.database.model.ShortcutItem;
/**
* Utility methods using package manager
*/
public class PackageManagerHelper {
private static final String TAG = "PackageManagerHelper";
private final Context mContext;
private final PackageManager mPm;
private final LauncherApps mLauncherApps;
public PackageManagerHelper(Context context) {
mContext = context;
mPm = context.getPackageManager();
mLauncherApps = (LauncherApps) context.getSystemService(Context.LAUNCHER_APPS_SERVICE);
}
/**
* Returns true if the app can possibly be on the SDCard. This is just a workaround and doesn't
* guarantee that the app is on SD card.
*/
public boolean isAppOnSdcard(String packageName, UserHandle user) {
ApplicationInfo info = null;
try {
info = mLauncherApps.getApplicationInfo(
packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, user);
return info != null && info.enabled && ((info.flags & ApplicationInfo.FLAG_INSTALLED) != 0)
&& (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
} catch (NameNotFoundException e) {
e.printStackTrace();
return false;
}
}
/**
* Returns whether the target app is suspended for a given user as per
* {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
*/
public boolean isAppSuspended(String packageName, UserHandle user) {
ApplicationInfo info = null;
try {
info = mLauncherApps.getApplicationInfo(packageName, 0, user);
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return info != null && info.enabled && ((info.flags & ApplicationInfo.FLAG_INSTALLED) != 0) &&
isAppSuspended(info);
}
public boolean isSafeMode() {
return mContext.getPackageManager().isSafeMode();
}
public Intent getAppLaunchIntent(String pkg, UserHandle user) {
List<LauncherActivityInfo> activities = mLauncherApps.getActivityList(pkg, user);
return activities.isEmpty() ? null :
ApplicationItem.makeLaunchIntent(activities.get(0));
}
/**
* Returns whether an application is suspended as per
* {@link android.app.admin.DevicePolicyManager#isPackageSuspended}.
*/
public static boolean isAppSuspended(ApplicationInfo info) {
// The value of FLAG_SUSPENDED was reused by a hidden constant
// ApplicationInfo.FLAG_PRIVILEGED prior to N, so only check for suspended flag on N
// or later.
if (Utilities.ATLEAST_NOUGAT) {
return (info.flags & ApplicationInfo.FLAG_SUSPENDED) != 0;
} else {
return false;
}
}
/**
* Returns true if {@param srcPackage} has the permission required to start the activity from
* {@param intent}. If {@param srcPackage} is null, then the activity should not need
* any permissions
*/
public boolean hasPermissionForActivity(Intent intent, String srcPackage) {
ResolveInfo target = mPm.resolveActivity(intent, 0);
if (target == null) {
// Not a valid target
return false;
}
if (TextUtils.isEmpty(target.activityInfo.permission)) {
// No permission is needed
return true;
}
if (TextUtils.isEmpty(srcPackage)) {
// The activity requires some permission but there is no source.
return false;
}
// Source does not have sufficient permissions.
if (mPm.checkPermission(target.activityInfo.permission, srcPackage) !=
PackageManager.PERMISSION_GRANTED) {
return false;
}
if (!Utilities.ATLEAST_MARSHMALLOW) {
// These checks are sufficient for below M devices.
return true;
}
// On M and above also check AppOpsManager for compatibility mode permissions.
if (TextUtils.isEmpty(AppOpsManager.permissionToOp(target.activityInfo.permission))) {
// There is no app-op for this permission, which could have been disabled.
return true;
}
// There is no direct way to check if the app-op is allowed for a particular app. Since
// app-op is only enabled for apps running in compatibility mode, simply block such apps.
try {
return mPm.getApplicationInfo(srcPackage, 0).targetSdkVersion >= Build.VERSION_CODES.M;
} catch (NameNotFoundException e) {
}
return false;
}
/**
* Starts the details activity for {@code info}
*/
public void startDetailsActivityForInfo(LauncherItem info, Rect sourceBounds, Bundle opts) {
ComponentName componentName = null;
if (info instanceof ApplicationItem) {
componentName = ((ApplicationItem) info).componentName;
} else if (info instanceof ShortcutItem) {
componentName = info.getTargetComponent();
}
if (componentName != null) {
try {
mLauncherApps.startAppDetailsActivity(
componentName, info.user.getRealHandle(), sourceBounds, opts);
} catch (SecurityException | ActivityNotFoundException e) {
Toast.makeText(mContext, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
Log.e(TAG, "Unable to launch settings", e);
}
}
}
}
......@@ -546,7 +546,7 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
void open();
void setHandler(com.android.quickstep.WindowTransformSwipeHandler handler);
void setHandler(WindowTransformSwipeHandler handler);
void finish();
}
......
/*
* Copyright (C) 2018 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 foundation.e.blisslauncher.features.quickstep;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.Keyframe;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.RectEvaluator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Property;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.view.ViewCompat;
import java.util.List;
import foundation.e.blisslauncher.R;
import foundation.e.blisslauncher.core.customviews.Insettable;
import static android.content.Context.ACCESSIBILITY_SERVICE;
import static android.view.MotionEvent.ACTION_DOWN;
/**
* Simple scrim which draws a flat color
*/
public class ScrimView extends View implements Insettable,
AccessibilityStateChangeListener, StateListener {
public static final Property<ScrimView, Integer> DRAG_HANDLE_ALPHA =
new Property<ScrimView, Integer>(Integer.TYPE, "dragHandleAlpha") {
@Override
public Integer get(ScrimView scrimView) {
return scrimView.mDragHandleAlpha;
}
@Override
public void set(ScrimView scrimView, Integer value) {
scrimView.setDragHandleAlpha(value);
}
};
private static final int WALLPAPERS = R.string.wallpaper_button_text;
private static final int WIDGETS = R.string.widget_button_text;
private static final int SETTINGS = R.string.settings_button_text;
private final Rect mTempRect = new Rect();
private final int[] mTempPos = new int[2];
protected final Launcher mLauncher;
private final AccessibilityManager mAM;
protected final int mEndScrim;
protected float mMaxScrimAlpha;
protected float mProgress = 1;
protected int mScrimColor;
protected int mCurrentFlatColor;
protected int mEndFlatColor;
protected int mEndFlatColorAlpha;
protected final int mDragHandleSize;
private final Rect mDragHandleBounds;
private final RectF mHitRect = new RectF();
private final AccessibilityHelper mAccessibilityHelper;
@Nullable
protected Drawable mDragHandle;
private int mDragHandleAlpha = 255;
public ScrimView(Context context, AttributeSet attrs) {
super(context, attrs);
mLauncher = Launcher.getLauncher(context);
mWallpaperColorInfo = WallpaperColorInfo.getInstance(context);
mEndScrim = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
mMaxScrimAlpha = 0.7f;
mDragHandleSize = context.getResources()
.getDimensionPixelSize(R.dimen.vertical_drag_handle_size);
mDragHandleBounds = new Rect(0, 0, mDragHandleSize, mDragHandleSize);
mAccessibilityHelper = createAccessibilityHelper();
ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
mAM = (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE);
setFocusable(false);
}
@NonNull
protected AccessibilityHelper createAccessibilityHelper() {
return new AccessibilityHelper();
}
@Override
public void setInsets(Rect insets) {
updateDragHandleBounds();
updateDragHandleVisibility(null);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
updateDragHandleBounds();
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mAM.addAccessibilityStateChangeListener(this);
onAccessibilityStateChanged(mAM.isEnabled());
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mAM.removeAccessibilityStateChangeListener(this);
}
@Override
public boolean hasOverlappingRendering() {
return false;
}
@Override
public void onExtractedColorsChanged(WallpaperColorInfo wallpaperColorInfo) {
mScrimColor = wallpaperColorInfo.getMainColor();
mEndFlatColor = compositeColors(mEndScrim, setAlphaComponent(
mScrimColor, Math.round(mMaxScrimAlpha * 255)));
mEndFlatColorAlpha = Color.alpha(mEndFlatColor);
updateColors();
invalidate();
}
public void setProgress(float progress) {
if (mProgress != progress) {
mProgress = progress;
updateColors();
updateDragHandleAlpha();
invalidate();
}
}
public void reInitUi() { }
protected void updateColors() {
mCurrentFlatColor = mProgress >= 1 ? 0 : setAlphaComponent(
mEndFlatColor, Math.round((1 - mProgress) * mEndFlatColorAlpha));
}
protected void updateDragHandleAlpha() {
if (mDragHandle != null) {
mDragHandle.setAlpha(mDragHandleAlpha);
}
}
private void setDragHandleAlpha(int alpha) {
if (alpha != mDragHandleAlpha) {
mDragHandleAlpha = alpha;
if (mDragHandle != null) {
mDragHandle.setAlpha(mDragHandleAlpha);
invalidate();
}
}
}
@Override
protected void onDraw(Canvas canvas) {
if (mCurrentFlatColor != 0) {
canvas.drawColor(mCurrentFlatColor);
}
if (mDragHandle != null) {
mDragHandle.draw(canvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean value = super.onTouchEvent(event);
if (!value && mDragHandle != null && event.getAction() == ACTION_DOWN
&& mDragHandle.getAlpha() == 255
&& mHitRect.contains(event.getX(), event.getY())) {
final Drawable drawable = mDragHandle;
mDragHandle = null;
drawable.setBounds(mDragHandleBounds);
Rect topBounds = new Rect(mDragHandleBounds);
topBounds.offset(0, -mDragHandleBounds.height() / 2);
Rect invalidateRegion = new Rect(mDragHandleBounds);
invalidateRegion.top = topBounds.top;
Keyframe frameTop = Keyframe.ofObject(0.6f, topBounds);
frameTop.setInterpolator(DEACCEL);
Keyframe frameBot = Keyframe.ofObject(1, mDragHandleBounds);
frameBot.setInterpolator(ACCEL);
PropertyValuesHolder holder = PropertyValuesHolder .ofKeyframe("bounds",
Keyframe.ofObject(0, mDragHandleBounds), frameTop, frameBot);
holder.setEvaluator(new RectEvaluator());
ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
getOverlay().remove(drawable);
updateDragHandleVisibility(drawable);
}
});
anim.addUpdateListener((v) -> invalidate(invalidateRegion));
getOverlay().add(drawable);
anim.start();
}
return value;
}
protected void updateDragHandleBounds() {
DeviceProfile grid = mLauncher.getDeviceProfile();
final int left;
final int width = getMeasuredWidth();
final int top = getMeasuredHeight() - mDragHandleSize - grid.getInsets().bottom;
final int topMargin;
if (grid.isVerticalBarLayout()) {
topMargin = grid.workspacePadding.bottom;
if (grid.isSeascape()) {
left = width - grid.getInsets().right - mDragHandleSize;
} else {
left = mDragHandleSize + grid.getInsets().left;
}
} else {
left = (width - mDragHandleSize) / 2;
topMargin = grid.hotseatBarSizePx;
}
mDragHandleBounds.offsetTo(left, top - topMargin);
mHitRect.set(mDragHandleBounds);
float inset = -mDragHandleSize / 2;
mHitRect.inset(inset, inset);
if (mDragHandle != null) {
mDragHandle.setBounds(mDragHandleBounds);
}
}
@Override
public void onAccessibilityStateChanged(boolean enabled) {
LauncherStateManager stateManager = mLauncher.getStateManager();
stateManager.removeStateListener(this);
if (enabled) {
stateManager.addStateListener(this);
onStateSetImmediately(mLauncher.getStateManager().getState());
} else {
setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
}
updateDragHandleVisibility(null);
}
private void updateDragHandleVisibility(Drawable recycle) {
boolean visible = mLauncher.getDeviceProfile().isVerticalBarLayout() || mAM.isEnabled();
boolean wasVisible = mDragHandle != null;
if (visible != wasVisible) {
if (visible) {
mDragHandle = recycle != null ? recycle :
mLauncher.getDrawable(R.drawable.drag_handle_indicator);
mDragHandle.setBounds(mDragHandleBounds);
updateDragHandleAlpha();
} else {
mDragHandle = null;
}
invalidate();
}
}
@Override
public boolean dispatchHoverEvent(MotionEvent event) {
return mAccessibilityHelper.dispatchHoverEvent(event) || super.dispatchHoverEvent(event);
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return mAccessibilityHelper.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
}
@Override
public void onFocusChanged(boolean gainFocus, int direction,
Rect previouslyFocusedRect) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
mAccessibilityHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
}
@Override
public void onStateTransitionStart(LauncherState toState) {}
@Override
public void onStateTransitionComplete(LauncherState finalState) {