├── Android.mk └── src └── com └── android └── internal └── utils └── du ├── ActionHolder.java ├── DUSystemReceiver.java ├── UserContentObserver.java ├── DUPackageMonitor.java ├── ImageHelper.java ├── Config.java ├── DUActionUtils.java ├── ActionConstants.java └── ActionHandler.java /Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH:= $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_SRC_FILES := $(call all-java-files-under, src) 6 | 7 | LOCAL_MODULE_TAGS := optional 8 | 9 | LOCAL_MODULE := org.dirtyunicorns.utils 10 | 11 | include $(BUILD_JAVA_LIBRARY) 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/ActionHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 TeamEos project 3 | * Author Randall Rushing aka bigrushdog, randall.rushing@gmail.com 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Widgets may implement this interface to interact with action configurations 18 | * 19 | */ 20 | 21 | package com.android.internal.utils.du; 22 | 23 | import com.android.internal.utils.du.ActionConstants.ConfigMap; 24 | import com.android.internal.utils.du.ActionConstants.Defaults; 25 | import com.android.internal.utils.du.Config.ActionConfig; 26 | import com.android.internal.utils.du.Config.ButtonConfig; 27 | 28 | public interface ActionHolder { 29 | public String getTag(); 30 | public void setTag(String tag); 31 | public Defaults getDefaults(); 32 | public void setDefaults(Defaults defaults); 33 | public ConfigMap getConfigMap(); 34 | public void setConfigMap(ConfigMap map); 35 | public ButtonConfig getButtonConfig(); 36 | public void setButtonConfig(ButtonConfig button); 37 | public ActionConfig getActionConfig(); 38 | public void setActionConfig(ActionConfig action); 39 | public ButtonConfig getDefaultButtonConfig(); 40 | public void setDefaultButtonConfig(ButtonConfig button); 41 | public ActionConfig getDefaultActionConfig(); 42 | public void setDefaultActionConfig(ActionConfig action); 43 | } 44 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/DUSystemReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2016 The TeamEos Project 3 | * 4 | * Author: Randall Rushing 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * A BroadcastReceiver that filters out broadcasts from non-system 19 | * related processes. Subclasses can allow additional broadcasting 20 | * packages by overriding onExemptBroadcast(Context context, String packageName) 21 | */ 22 | 23 | package com.android.internal.utils.du; 24 | 25 | import android.content.BroadcastReceiver; 26 | import android.content.Context; 27 | import android.content.Intent; 28 | 29 | public abstract class DUSystemReceiver extends BroadcastReceiver { 30 | 31 | protected abstract void onSecureReceive(Context context, Intent intent); 32 | 33 | protected boolean onExemptBroadcast(Context context, String packageName) { 34 | return false; 35 | } 36 | 37 | @Override 38 | public final void onReceive(Context context, Intent intent) { 39 | if (context == null || intent == null) { 40 | return; 41 | } 42 | if (isBroadcastFromSystem(context)) { 43 | onSecureReceive(context, intent); 44 | } 45 | } 46 | 47 | private boolean isBroadcastFromSystem(Context context) { 48 | String packageName = context.getPackageName(); 49 | if (packageName == null 50 | && android.os.Process.SYSTEM_UID == context.getApplicationInfo().uid) { 51 | packageName = "android"; 52 | } 53 | if (packageName == null) { 54 | return false; 55 | } 56 | if (packageName.equals("com.android.systemui") 57 | || packageName.equals("com.android.keyguard") 58 | || packageName.equals("com.android.settings") 59 | || packageName.equals("android") 60 | || context.getApplicationInfo().uid == android.os.Process.SYSTEM_UID) { 61 | return true; 62 | } 63 | if (onExemptBroadcast(context, packageName)) { 64 | return true; 65 | } 66 | return false; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/UserContentObserver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The CyanogenMod Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License 15 | */ 16 | package com.android.internal.utils.du; 17 | 18 | import android.app.ActivityManagerNative; 19 | import android.app.IUserSwitchObserver; 20 | import android.database.ContentObserver; 21 | import android.net.Uri; 22 | import android.os.Handler; 23 | import android.os.IRemoteCallback; 24 | import android.os.RemoteException; 25 | import android.util.Log; 26 | 27 | /** 28 | * Simple extension of ContentObserver that also listens for user switch events to call update 29 | */ 30 | public abstract class UserContentObserver extends ContentObserver { 31 | private static final String TAG = "UserContentObserver"; 32 | 33 | private Runnable mUpdateRunnable; 34 | 35 | private IUserSwitchObserver mUserSwitchObserver = new IUserSwitchObserver.Stub() { 36 | @Override 37 | public void onUserSwitching(int newUserId, IRemoteCallback reply) { 38 | } 39 | @Override 40 | public void onUserSwitchComplete(int newUserId) throws RemoteException { 41 | mHandler.post(mUpdateRunnable); 42 | } 43 | @Override 44 | public void onForegroundProfileSwitch(int newProfileId) { 45 | } 46 | @Override 47 | public void onLockedBootComplete(int val) { 48 | } 49 | }; 50 | 51 | private Handler mHandler; 52 | 53 | public UserContentObserver(Handler handler) { 54 | super(handler); 55 | mHandler = handler; 56 | mUpdateRunnable = new Runnable() { 57 | @Override 58 | public void run() { 59 | update(); 60 | } 61 | }; 62 | } 63 | 64 | protected void observe() { 65 | try { 66 | ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchObserver, TAG); 67 | } catch (RemoteException e) { 68 | Log.w(TAG, "Unable to register user switch observer!", e); 69 | } 70 | } 71 | 72 | protected void unobserve() { 73 | try { 74 | mHandler.removeCallbacks(mUpdateRunnable); 75 | ActivityManagerNative.getDefault().unregisterUserSwitchObserver(mUserSwitchObserver); 76 | } catch (RemoteException e) { 77 | Log.w(TAG, "Unable to unregister user switch observer!", e); 78 | } 79 | } 80 | 81 | protected abstract void update(); 82 | 83 | @Override 84 | public void onChange(boolean selfChange) { 85 | update(); 86 | } 87 | 88 | @Override 89 | public void onChange(boolean selfChange, Uri uri) { 90 | update(); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/DUPackageMonitor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015-2016 The TeamEos Project 3 | * 4 | * Author: Randall Rushing 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * A simplified package monitor class with easy-to-use callbacks when a 19 | * state changes. We register the receiver on background thread but post events 20 | * to the UI thread 21 | */ 22 | 23 | package com.android.internal.utils.du; 24 | 25 | import android.content.Context; 26 | import android.os.Handler; 27 | import android.os.Message; 28 | 29 | import java.util.ArrayList; 30 | 31 | public class DUPackageMonitor extends com.android.internal.content.PackageMonitor { 32 | private static final int MSG_PACKAGE_ADDED = 1; 33 | private static final int MSG_PACKAGE_REMOVED = 2; 34 | private static final int MSG_PACKAGE_CHANGED = 3; 35 | 36 | public static enum PackageState { 37 | PACKAGE_REMOVED, 38 | PACKAGE_ADDED, 39 | PACKAGE_CHANGED 40 | } 41 | 42 | public interface PackageChangedListener { 43 | public void onPackageChanged(String pkg, PackageState state); 44 | } 45 | 46 | private Handler mHandler; 47 | 48 | private ArrayList mListeners = new ArrayList(); 49 | 50 | public void register(Context context, Handler foreground) { 51 | register(context, null, null, true); 52 | 53 | mHandler = new Handler(foreground.getLooper()) { 54 | @Override 55 | public void handleMessage(Message msg) { 56 | switch (msg.what) { 57 | case MSG_PACKAGE_ADDED: 58 | for (PackageChangedListener listener : mListeners) { 59 | listener.onPackageChanged((String) msg.obj, PackageState.PACKAGE_ADDED); 60 | } 61 | break; 62 | case MSG_PACKAGE_REMOVED: 63 | for (PackageChangedListener listener : mListeners) { 64 | listener.onPackageChanged((String) msg.obj, 65 | PackageState.PACKAGE_REMOVED); 66 | } 67 | break; 68 | case MSG_PACKAGE_CHANGED: 69 | for (PackageChangedListener listener : mListeners) { 70 | listener.onPackageChanged((String) msg.obj, 71 | PackageState.PACKAGE_CHANGED); 72 | } 73 | break; 74 | } 75 | } 76 | }; 77 | } 78 | 79 | public void addListener(PackageChangedListener listener) { 80 | if (listener != null) { 81 | mListeners.add(listener); 82 | } 83 | } 84 | 85 | public void removeListener(PackageChangedListener listener) { 86 | if (listener != null) { 87 | mListeners.remove(listener); 88 | } 89 | } 90 | 91 | /** 92 | * Called when a package is really added (and not replaced). 93 | */ 94 | public void onPackageAdded(String packageName, int uid) { 95 | Message msg = mHandler.obtainMessage(MSG_PACKAGE_ADDED, packageName); 96 | mHandler.sendMessage(msg); 97 | } 98 | 99 | /** 100 | * Called when a package is really removed (and not replaced). 101 | */ 102 | public void onPackageRemoved(String packageName, int uid) { 103 | Message msg = mHandler.obtainMessage(MSG_PACKAGE_REMOVED, packageName); 104 | mHandler.sendMessage(msg); 105 | } 106 | 107 | /** 108 | * Direct reflection of {@link Intent#ACTION_PACKAGE_CHANGED Intent.ACTION_PACKAGE_CHANGED} 109 | * being received, informing you of changes to the enabled/disabled state of components in a 110 | * package and/or of the overall package. 111 | * 112 | * @param packageName The name of the package that is changing. 113 | * @param uid The user ID the package runs under. 114 | * @param components Any components in the package that are changing. If the overall package is 115 | * changing, this will contain an entry of the package name itself. 116 | * @return Return true to indicate you care about this change, which will result in 117 | * {@link #onSomePackagesChanged()} being called later. If you return false, no further 118 | * callbacks will happen about this change. The default implementation returns true if 119 | * this is a change to the entire package. 120 | */ 121 | public boolean onPackageChanged(String packageName, int uid, String[] components) { 122 | Message msg = mHandler.obtainMessage(MSG_PACKAGE_CHANGED, packageName); 123 | mHandler.sendMessage(msg); 124 | return super.onPackageChanged(packageName, uid, components); 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/ImageHelper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 SlimRoms Project 3 | * Copyright (C) 2015 TeamEos Project 4 | * Copyright (C) 2015-2016 The DirtyUnicorns Project 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | package com.android.internal.utils.du; 20 | 21 | import java.io.File; 22 | import java.io.FileDescriptor; 23 | import java.io.FileNotFoundException; 24 | import java.io.FileOutputStream; 25 | import java.io.IOException; 26 | 27 | import org.xmlpull.v1.XmlPullParser; 28 | import org.xmlpull.v1.XmlPullParserException; 29 | 30 | import android.content.Context; 31 | import android.content.res.Resources; 32 | import android.graphics.Bitmap; 33 | import android.graphics.Bitmap.Config; 34 | import android.graphics.BitmapFactory; 35 | import android.graphics.BitmapShader; 36 | import android.graphics.Canvas; 37 | import android.graphics.ColorMatrix; 38 | import android.graphics.ColorMatrixColorFilter; 39 | import android.graphics.Matrix; 40 | import android.graphics.Paint; 41 | import android.graphics.PorterDuff; 42 | import android.graphics.PorterDuffColorFilter; 43 | import android.graphics.PorterDuffXfermode; 44 | import android.graphics.PorterDuff.Mode; 45 | import android.graphics.Rect; 46 | import android.graphics.RectF; 47 | import android.graphics.Shader.TileMode; 48 | import android.graphics.drawable.BitmapDrawable; 49 | import android.graphics.drawable.Drawable; 50 | import android.graphics.drawable.VectorDrawable; 51 | import android.net.Uri; 52 | import android.os.ParcelFileDescriptor; 53 | import android.util.AttributeSet; 54 | import android.util.Log; 55 | import android.util.TypedValue; 56 | import android.util.Xml; 57 | 58 | public class ImageHelper { 59 | private static final int VECTOR_WIDTH = 512; 60 | private static final int VECTOR_HEIGHT = 512; 61 | 62 | public static Drawable getColoredDrawable(Drawable d, int color) { 63 | if (d == null) { 64 | return null; 65 | } 66 | if (d instanceof VectorDrawable) { 67 | d.setTint(color); 68 | return d; 69 | } 70 | Bitmap colorBitmap = ((BitmapDrawable) d).getBitmap(); 71 | Bitmap grayscaleBitmap = toGrayscale(colorBitmap); 72 | Paint pp = new Paint(); 73 | pp.setAntiAlias(true); 74 | PorterDuffColorFilter frontFilter = 75 | new PorterDuffColorFilter(color, Mode.MULTIPLY); 76 | pp.setColorFilter(frontFilter); 77 | Canvas cc = new Canvas(grayscaleBitmap); 78 | final Rect rect = new Rect(0, 0, grayscaleBitmap.getWidth(), grayscaleBitmap.getHeight()); 79 | cc.drawBitmap(grayscaleBitmap, rect, rect, pp); 80 | return new BitmapDrawable(grayscaleBitmap); 81 | } 82 | 83 | public static Bitmap drawableToBitmap (Drawable drawable) { 84 | if (drawable == null) { 85 | return null; 86 | } else if (drawable instanceof BitmapDrawable) { 87 | return ((BitmapDrawable) drawable).getBitmap(); 88 | } 89 | Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), 90 | drawable.getIntrinsicHeight(), Config.ARGB_8888); 91 | Canvas canvas = new Canvas(bitmap); 92 | drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 93 | drawable.draw(canvas); 94 | return bitmap; 95 | } 96 | 97 | public static Bitmap getColoredBitmap(Drawable d, int color) { 98 | if (d == null) { 99 | return null; 100 | } 101 | Bitmap colorBitmap = ((BitmapDrawable) d).getBitmap(); 102 | Bitmap grayscaleBitmap = toGrayscale(colorBitmap); 103 | Paint pp = new Paint(); 104 | pp.setAntiAlias(true); 105 | PorterDuffColorFilter frontFilter = 106 | new PorterDuffColorFilter(color, Mode.MULTIPLY); 107 | pp.setColorFilter(frontFilter); 108 | Canvas cc = new Canvas(grayscaleBitmap); 109 | final Rect rect = new Rect(0, 0, grayscaleBitmap.getWidth(), grayscaleBitmap.getHeight()); 110 | cc.drawBitmap(grayscaleBitmap, rect, rect, pp); 111 | return grayscaleBitmap; 112 | } 113 | 114 | private static Bitmap toGrayscale(Bitmap bmpOriginal) { 115 | int width, height; 116 | height = bmpOriginal.getHeight(); 117 | width = bmpOriginal.getWidth(); 118 | 119 | Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); 120 | Canvas c = new Canvas(bmpGrayscale); 121 | Paint paint = new Paint(); 122 | paint.setAntiAlias(true); 123 | ColorMatrix cm = new ColorMatrix(); 124 | final Rect rect = new Rect(0, 0, width, height); 125 | cm.setSaturation(0); 126 | 127 | ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm); 128 | paint.setColorFilter(f); 129 | c.drawBitmap(bmpOriginal, rect, rect, paint); 130 | return bmpGrayscale; 131 | } 132 | 133 | public static Drawable resize(Context context, Drawable image, int size) { 134 | if (image == null || context == null) { 135 | return null; 136 | } 137 | if (image instanceof VectorDrawable) { 138 | return image; 139 | } else { 140 | int newSize = DUActionUtils.dpToPx(context, size); 141 | Bitmap bitmap = ((BitmapDrawable) image).getBitmap(); 142 | Bitmap scaledBitmap = Bitmap.createBitmap(newSize, newSize, Config.ARGB_8888); 143 | 144 | float ratioX = newSize / (float) bitmap.getWidth(); 145 | float ratioY = newSize / (float) bitmap.getHeight(); 146 | float middleX = newSize / 2.0f; 147 | float middleY = newSize / 2.0f; 148 | 149 | final Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG); 150 | paint.setAntiAlias(true); 151 | 152 | Matrix scaleMatrix = new Matrix(); 153 | scaleMatrix.setScale(ratioX, ratioY, middleX, middleY); 154 | 155 | Canvas canvas = new Canvas(scaledBitmap); 156 | canvas.setMatrix(scaleMatrix); 157 | canvas.drawBitmap(bitmap, middleX - bitmap.getWidth() / 2, 158 | middleY - bitmap.getHeight() / 2, paint); 159 | return new BitmapDrawable(context.getResources(), scaledBitmap); 160 | } 161 | } 162 | 163 | public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) { 164 | if (bitmap == null) { 165 | return null; 166 | } 167 | Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), 168 | Config.ARGB_8888); 169 | Canvas canvas = new Canvas(output); 170 | 171 | final int color = 0xff424242; 172 | final Paint paint = new Paint(); 173 | final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 174 | final RectF rectF = new RectF(rect); 175 | final float roundPx = 24; 176 | paint.setAntiAlias(true); 177 | canvas.drawARGB(0, 0, 0, 0); 178 | paint.setColor(color); 179 | canvas.drawRoundRect(rectF, roundPx, roundPx, paint); 180 | paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 181 | canvas.drawBitmap(bitmap, rect, rect, paint); 182 | return output; 183 | } 184 | 185 | public static Bitmap getCircleBitmap(Bitmap bitmap) { 186 | if (bitmap == null) { 187 | return null; 188 | } 189 | int width = bitmap.getWidth(); 190 | int height = bitmap.getHeight(); 191 | 192 | Bitmap output = Bitmap.createBitmap(width, height, 193 | Config.ARGB_8888); 194 | Canvas canvas = new Canvas(output); 195 | 196 | BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP); 197 | final Paint paint = new Paint(); 198 | paint.setAntiAlias(true); 199 | paint.setShader(shader); 200 | 201 | canvas.drawCircle(width/2, height/2, width/2, paint); 202 | 203 | return output; 204 | } 205 | 206 | public static Drawable getVector(Resources res, int resId) { 207 | return getVector(res, resId, 0, 0, false); 208 | } 209 | 210 | public static Drawable getVector(Resources res, int resId, int width, int height) { 211 | return getVector(res, resId, width, height, false); 212 | } 213 | 214 | public static Drawable getVector(Resources res, int resId, boolean toBitmapDrawable) { 215 | return getVector(res, resId, 0, 0, toBitmapDrawable); 216 | } 217 | 218 | public static Drawable getVector(Resources res, int resId, int width, int height, 219 | boolean toBitmapDrawable) { 220 | if (width <= 0) { 221 | width = VECTOR_WIDTH; 222 | } 223 | if (height <= 0) { 224 | width = VECTOR_HEIGHT; 225 | } 226 | 227 | VectorDrawable vectorDrawable = new VectorDrawable(); 228 | vectorDrawable.setBounds(0, 0, width, height); 229 | try { 230 | XmlPullParser parser = res.getXml(resId); 231 | AttributeSet attrs = Xml.asAttributeSet(parser); 232 | 233 | int type; 234 | while ((type = parser.next()) != XmlPullParser.START_TAG && 235 | type != XmlPullParser.END_DOCUMENT) { 236 | // Empty loop 237 | } 238 | 239 | if (type != XmlPullParser.START_TAG) { 240 | // Log.e("ImageHelper VectorLoader", "No start tag found"); 241 | } 242 | 243 | vectorDrawable.inflate(res, parser, attrs); 244 | 245 | if (!toBitmapDrawable) { 246 | return vectorDrawable; 247 | } 248 | 249 | return new BitmapDrawable(res, drawableToBitmap(vectorDrawable)); 250 | } catch (Exception e) { 251 | // Log.e("ImageHelper VectorLoader", "Error loading resource ID " + String.valueOf(resId) + " Try loading as a non vector"); 252 | return null; 253 | } 254 | } 255 | 256 | /** 257 | * @param context callers context 258 | * @param uri Uri to handle 259 | * @return A bitmap from the requested uri 260 | * @throws IOException 261 | * 262 | * @Credit: StackOverflow 263 | * http://stackoverflow.com/questions/35909008/pick-image 264 | * -from-gallery-or-google-photos-failing 265 | */ 266 | public static Bitmap getBitmapFromUri(Context context, Uri uri) throws IOException { 267 | if (context == null || uri == null) { 268 | return null; 269 | } 270 | ParcelFileDescriptor parcelFileDescriptor = 271 | context.getContentResolver().openFileDescriptor(uri, "r"); 272 | FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor(); 273 | Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor); 274 | parcelFileDescriptor.close(); 275 | return image; 276 | } 277 | 278 | /** 279 | * @param storageDir Desired location in storage as a File 280 | * @param fileName Name of bitmap file to store 281 | * @param bitmap the bitmap to store 282 | * @return the Uri of the bitmap 283 | */ 284 | public static Uri addBitmapToStorage(File storageDir, String fileName, Bitmap bitmap) { 285 | if (storageDir == null || fileName == null || bitmap == null) { 286 | return null; 287 | } 288 | File imageFile = new File(storageDir, fileName); 289 | try { 290 | FileOutputStream fos = new FileOutputStream(imageFile); 291 | bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos); 292 | fos.flush(); 293 | fos.close(); 294 | } catch (Exception e) { 295 | return null; 296 | } 297 | return Uri.fromFile(imageFile); 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/Config.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 TeamEos project 3 | * Author Randall Rushing aka bigrushdog, randall.rushing@gmail.com 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Config.java: A helper class for loading/setting feature button configurations 18 | * to SettingsProvider. We start with defining a "action" in the nested 19 | * ActionConfig class. A action holds a raw action string, a label for that action, 20 | * and helper functions for loading an associated drawable for that action. 21 | * 22 | * The nested static class ButtonConfig is a convenience class that holds three 23 | * ActionConfig objects. Those ActionConfig objects are labeled as "PRIMARY", 24 | * "SECOND", and "THIRD", which will typically refer to a single tap, long press, 25 | * and double tap, respectively. However, this is not always the case, thus the 26 | * more generalized naming convention. 27 | * 28 | * ActionConfig and ButtonConfig implement the private Stringable interface to allow 29 | * for easy loading and setting 30 | * 31 | */ 32 | package com.android.internal.utils.du; 33 | 34 | import java.util.ArrayList; 35 | import java.util.Arrays; 36 | import java.util.List; 37 | 38 | import com.android.internal.utils.du.ActionHandler; 39 | import com.android.internal.utils.du.ActionConstants.ConfigMap; 40 | import com.android.internal.utils.du.ActionConstants.Defaults; 41 | 42 | import android.content.Context; 43 | import android.graphics.drawable.Drawable; 44 | import android.net.Uri; 45 | import android.os.Parcel; 46 | import android.os.Parcelable; 47 | import android.os.UserHandle; 48 | import android.provider.Settings; 49 | import android.text.TextUtils; 50 | 51 | public class Config { 52 | private interface Stringable { 53 | public String toDelimitedString(); 54 | public void fromList(Context ctx, List items); 55 | } 56 | 57 | /** 58 | * For use with action/button based features that don't require a defaut configuration 59 | */ 60 | public static ArrayList getConfig(Context ctx, String uri, 61 | boolean fromSecureSettings) { 62 | if (ctx == null || uri == null) { 63 | return null; 64 | } 65 | String config; 66 | if (fromSecureSettings) { 67 | config = Settings.Secure.getStringForUser( 68 | ctx.getContentResolver(), uri, 69 | UserHandle.USER_CURRENT); 70 | } else { 71 | config = Settings.System.getStringForUser( 72 | ctx.getContentResolver(), uri, 73 | UserHandle.USER_CURRENT); 74 | } 75 | if (TextUtils.isEmpty(config)) { 76 | return null; 77 | } 78 | ArrayList items = new ArrayList(); 79 | items.addAll(Arrays.asList(config.split("\\|"))); // split string into array elements 80 | int numConfigs = Integer.parseInt(items.get(0)); // first element is always the number of 81 | // ButtonConfigs to parse 82 | items.remove(0); // remove button count for a clean list of buttons 83 | 84 | ArrayList buttonList = new ArrayList(); 85 | ButtonConfig buttonConfig; 86 | 87 | for (int i = 0; i < numConfigs; i++) { 88 | int from = i * ButtonConfig.NUM_ELEMENTS; // (0, 10), (10, 20)... 89 | int to = from + ButtonConfig.NUM_ELEMENTS; 90 | buttonConfig = new ButtonConfig(ctx); 91 | buttonConfig.fromList(ctx, items.subList(from, to)); // initialize button from list 92 | // elements 93 | buttonList.add(buttonConfig); 94 | } 95 | return buttonList; 96 | } 97 | 98 | public static ArrayList getConfig(Context ctx, Defaults defaults) { 99 | if (ctx == null || defaults == null) { 100 | return null; 101 | } 102 | String config = Settings.Secure.getStringForUser( 103 | ctx.getContentResolver(), defaults.getUri(), 104 | UserHandle.USER_CURRENT); 105 | if (TextUtils.isEmpty(config)) { 106 | config = defaults.getDefaultConfig(); 107 | } 108 | 109 | ArrayList items = new ArrayList(); 110 | items.addAll(Arrays.asList(config.split("\\|"))); // split string into array elements 111 | int numConfigs = Integer.parseInt(items.get(0)); // first element is always the number of ButtonConfigs to parse 112 | items.remove(0); // remove button count for a clean list of buttons 113 | 114 | ArrayList buttonList = new ArrayList(); 115 | ButtonConfig buttonConfig; 116 | 117 | for (int i = 0; i < numConfigs; i++) { 118 | int from = i * ButtonConfig.NUM_ELEMENTS; // (0, 10), (10, 20)... 119 | int to = from + ButtonConfig.NUM_ELEMENTS; 120 | buttonConfig = new ButtonConfig(ctx); 121 | buttonConfig.fromList(ctx, items.subList(from, to)); // initialize button from list elements 122 | buttonList.add(buttonConfig); 123 | } 124 | return buttonList; 125 | } 126 | 127 | public static ArrayList getDefaultConfig(Context ctx, Defaults defaults) { 128 | if (ctx == null || defaults == null) { 129 | return null; 130 | } 131 | String config = defaults.getDefaultConfig(); 132 | ArrayList items = new ArrayList(); 133 | items.addAll(Arrays.asList(config.split("\\|"))); 134 | int numConfigs = Integer.parseInt(items.get(0)); 135 | items.remove(0); 136 | ArrayList buttonList = new ArrayList(); 137 | ButtonConfig buttonConfig; 138 | 139 | for (int i = 0; i < numConfigs; i++) { 140 | int from = i * ButtonConfig.NUM_ELEMENTS; 141 | int to = from + ButtonConfig.NUM_ELEMENTS; 142 | buttonConfig = new ButtonConfig(ctx); 143 | buttonConfig.fromList(ctx, items.subList(from, to)); 144 | buttonList.add(buttonConfig); 145 | } 146 | return buttonList; 147 | } 148 | 149 | public static void setConfig(Context ctx, Defaults defaults, ArrayList config) { 150 | if (ctx == null || defaults == null || config == null) { 151 | return; 152 | } 153 | int numConfigs = config.size(); 154 | if (numConfigs <= 0) { 155 | return; 156 | } 157 | StringBuilder b = new StringBuilder(); 158 | b.append(String.valueOf(numConfigs)); 159 | b.append(ActionConstants.ACTION_DELIMITER); // size of list is always first element 160 | for (ButtonConfig button : config) { 161 | b.append(button.toDelimitedString()); // this is just beautiful ;D 162 | } 163 | String s = b.toString(); 164 | if (s.endsWith(ActionConstants.ACTION_DELIMITER)) { 165 | s = removeLastChar(s); // trim final delimiter if need be 166 | } 167 | Settings.Secure.putStringForUser(ctx.getContentResolver(), defaults.getUri(), s, 168 | UserHandle.USER_CURRENT); 169 | } 170 | 171 | public static ButtonConfig getButtonConfigFromTag(ArrayList configs, String tag) { 172 | if (configs == null || tag == null) { 173 | return null; 174 | } 175 | ButtonConfig config = null; 176 | for (ButtonConfig b : configs) { 177 | if (TextUtils.equals(b.getTag(), tag)) { 178 | config = b; 179 | break; 180 | } 181 | } 182 | return config; 183 | } 184 | 185 | public static ArrayList replaceButtonAtPosition(ArrayList configs, 186 | ButtonConfig button, ConfigMap map) { 187 | if (configs == null || button == null || map == null) { 188 | return null; 189 | } 190 | configs.remove(map.button); 191 | configs.add(map.button, button); 192 | return configs; 193 | } 194 | 195 | public static String removeLastChar(String s) { 196 | if (s == null || s.length() == 0) { 197 | return s; 198 | } 199 | return s.substring(0, s.length() - 1); 200 | } 201 | 202 | public static class ButtonConfig implements Stringable, Parcelable { 203 | public static final int NUM_ELEMENTS = 10; 204 | protected ActionConfig[] configs = new ActionConfig[3]; 205 | private String tag = ActionConstants.EMPTY; 206 | 207 | // internal use only 208 | private ButtonConfig() { 209 | } 210 | 211 | public ButtonConfig(Context ctx) { 212 | configs[ActionConfig.PRIMARY] = new ActionConfig(ctx); 213 | configs[ActionConfig.SECOND] = new ActionConfig(ctx); 214 | configs[ActionConfig.THIRD] = new ActionConfig(ctx); 215 | } 216 | 217 | public String getTag() { 218 | return tag; 219 | } 220 | 221 | public void setTag(String tag) { 222 | this.tag = tag; 223 | } 224 | 225 | public boolean hasCustomIcon() { 226 | return configs[ActionConfig.PRIMARY].hasCustomIcon(); 227 | } 228 | 229 | public void clearCustomIconIconUri() { 230 | configs[ActionConfig.PRIMARY].clearCustomIconIconUri(); 231 | } 232 | 233 | public void setCustomIconUri(String type, String packageName, String iconName) { 234 | configs[ActionConfig.PRIMARY].setCustomIconUri(type, packageName, iconName); 235 | } 236 | 237 | public void setCustomImageUri(Uri uri) { 238 | configs[ActionConfig.PRIMARY].setCustomImageUri(uri); 239 | } 240 | 241 | public Drawable getDefaultIcon(Context ctx) { 242 | return configs[ActionConfig.PRIMARY].getDefaultIcon(ctx); 243 | } 244 | 245 | public Drawable getCurrentIcon(Context ctx) { 246 | return configs[ActionConfig.PRIMARY].getCurrentIcon(ctx); 247 | } 248 | 249 | public boolean isSystemAction() { 250 | return configs[ActionConfig.PRIMARY].isSystemAction(); 251 | } 252 | 253 | public String getSystemActionIconName() { 254 | return configs[ActionConfig.PRIMARY].getSystemActionIconName(); 255 | } 256 | 257 | public ActionConfig getActionConfig(int which) { 258 | if (which < ActionConfig.PRIMARY || which > ActionConfig.THIRD) { 259 | return null; 260 | } 261 | return configs[which]; 262 | } 263 | 264 | public void setActionConfig(ActionConfig config, int which) { 265 | if (which < ActionConfig.PRIMARY || which > ActionConfig.THIRD || config == null) { 266 | return; 267 | } 268 | configs[which] = config; 269 | } 270 | 271 | public static void setButton(Context ctx, ButtonConfig button, String uri, boolean isSecure) { 272 | StringBuilder b = new StringBuilder(); 273 | b.append(button.toDelimitedString()); // this is just beautiful ;D 274 | String s = b.toString(); 275 | if (s.endsWith(ActionConstants.ACTION_DELIMITER)) { 276 | s = removeLastChar(s); // trim final delimiter if need be 277 | } 278 | 279 | if (isSecure) { 280 | Settings.Secure.putStringForUser(ctx.getContentResolver(), uri, s, 281 | UserHandle.USER_CURRENT); 282 | } else { 283 | Settings.System.putStringForUser(ctx.getContentResolver(), uri, s, 284 | UserHandle.USER_CURRENT); 285 | } 286 | } 287 | 288 | public static ButtonConfig getButton(Context ctx, String uri, boolean isSecure) { 289 | if (ctx == null || TextUtils.isEmpty(uri)) { 290 | return null; 291 | } 292 | String config; 293 | if (isSecure) { 294 | config = Settings.Secure.getStringForUser( 295 | ctx.getContentResolver(), uri, 296 | UserHandle.USER_CURRENT); 297 | } else { 298 | config = Settings.System.getStringForUser( 299 | ctx.getContentResolver(), uri, 300 | UserHandle.USER_CURRENT); 301 | } 302 | if (TextUtils.isEmpty(config)) { 303 | return new ButtonConfig(ctx); 304 | } 305 | ArrayList items = new ArrayList(); 306 | items.addAll(Arrays.asList(config.split("\\|"))); 307 | ButtonConfig buttonConfig = new ButtonConfig(ctx); 308 | buttonConfig.fromList(ctx, items.subList(0, NUM_ELEMENTS)); // initialize button from 309 | // list elements 310 | return buttonConfig; 311 | } 312 | 313 | @Override 314 | public String toDelimitedString() { 315 | return tag + ActionConstants.ACTION_DELIMITER 316 | + configs[ActionConfig.PRIMARY].toDelimitedString() 317 | + configs[ActionConfig.SECOND].toDelimitedString() 318 | + configs[ActionConfig.THIRD].toDelimitedString(); 319 | } 320 | 321 | @Override 322 | public void fromList(Context ctx, List items) { 323 | ArrayList buttons = new ArrayList(); 324 | buttons.addAll(items); 325 | tag = buttons.get(0); 326 | 327 | ActionConfig config = new ActionConfig(); 328 | config.fromList(ctx, buttons.subList(1, 4)); 329 | configs[ActionConfig.PRIMARY] = config; 330 | 331 | config = new ActionConfig(); 332 | config.fromList(ctx, buttons.subList(4, 7)); 333 | configs[ActionConfig.SECOND] = config; 334 | 335 | config = new ActionConfig(); 336 | config.fromList(ctx, buttons.subList(7, 10)); 337 | configs[ActionConfig.THIRD] = config; 338 | } 339 | 340 | @Override 341 | public int describeContents() { 342 | return 0; 343 | } 344 | 345 | @Override 346 | public void writeToParcel(Parcel dest, int flags) { 347 | dest.writeString(tag); 348 | dest.writeParcelable(configs[ActionConfig.PRIMARY], flags); 349 | dest.writeParcelable(configs[ActionConfig.SECOND], flags); 350 | dest.writeParcelable(configs[ActionConfig.THIRD], flags); 351 | } 352 | 353 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 354 | public ButtonConfig createFromParcel(Parcel in) { 355 | return new ButtonConfig(in); 356 | } 357 | 358 | public ButtonConfig[] newArray(int size) { 359 | return new ButtonConfig[size]; 360 | } 361 | }; 362 | 363 | private ButtonConfig(Parcel in) { 364 | tag = in.readString(); 365 | configs[ActionConfig.PRIMARY] = (ActionConfig) in.readParcelable(Config.ActionConfig.class 366 | .getClassLoader()); 367 | configs[ActionConfig.SECOND] = (ActionConfig) in.readParcelable(Config.ActionConfig.class 368 | .getClassLoader()); 369 | configs[ActionConfig.THIRD] = (ActionConfig) in.readParcelable(Config.ActionConfig.class 370 | .getClassLoader()); 371 | } 372 | } 373 | 374 | public static class ActionConfig implements Stringable, Comparable, Parcelable { 375 | public static final int PRIMARY = 0; 376 | public static final int SECOND = 1; 377 | public static final int THIRD = 2; 378 | 379 | private String action = ActionHandler.SYSTEMUI_TASK_NO_ACTION; 380 | private String label = ActionConstants.EMPTY; 381 | private String iconUri = ActionConstants.EMPTY; 382 | 383 | // internal use only 384 | private ActionConfig() { 385 | } 386 | 387 | public static ActionConfig create(Context ctx) { 388 | return new ActionConfig(ctx); 389 | } 390 | 391 | public static ActionConfig create(Context ctx, String action) { 392 | return new ActionConfig(ctx, action); 393 | } 394 | 395 | public static ActionConfig create(Context ctx, String action, String iconUri) { 396 | return new ActionConfig(ctx, action, iconUri); 397 | } 398 | 399 | public ActionConfig(Context ctx) { 400 | label = DUActionUtils.getFriendlyNameForUri(ctx, action); 401 | } 402 | 403 | public ActionConfig(Context ctx, String action) { 404 | this.action = action; 405 | label = DUActionUtils.getFriendlyNameForUri(ctx, action); 406 | } 407 | 408 | public ActionConfig(Context ctx, String action, String iconUri) { 409 | this(ctx, action); 410 | this.iconUri = iconUri; 411 | } 412 | 413 | public String getAction() { 414 | return action; 415 | } 416 | 417 | public String getLabel() { 418 | return label; 419 | } 420 | 421 | public String getIconUri() { 422 | if (!hasCustomIcon()) { 423 | return action; 424 | } else { 425 | return iconUri; 426 | } 427 | } 428 | 429 | public boolean hasCustomIcon() { 430 | return !TextUtils.equals(ActionConstants.EMPTY, iconUri); 431 | } 432 | 433 | public void clearCustomIconIconUri() { 434 | iconUri = ActionConstants.EMPTY; 435 | } 436 | 437 | public boolean isSystemAction() { 438 | return action.startsWith(ActionHandler.SYSTEM_PREFIX); 439 | } 440 | 441 | public String getSystemActionIconName() { 442 | if (action.startsWith(ActionHandler.SYSTEM_PREFIX)) { 443 | for (int i = 0; i < ActionHandler.systemActions.length; i++) { 444 | if (ActionHandler.systemActions[i].mAction.equals(action)) { 445 | return ActionHandler.systemActions[i].mIconRes; 446 | } 447 | } 448 | } 449 | return null; 450 | } 451 | 452 | public void setCustomImageUri(Uri uri) { 453 | iconUri = "image$" + uri.toString(); 454 | } 455 | 456 | public void setCustomIconUri(String type, String packageName, String iconName) { 457 | StringBuilder b = new StringBuilder() 458 | .append(type) 459 | .append("$") 460 | .append(packageName) 461 | .append("$") 462 | .append(iconName); 463 | iconUri = b.toString(); 464 | } 465 | 466 | public Drawable getDefaultIcon(Context ctx) { 467 | return DUActionUtils.getDrawableForAction(ctx, action); 468 | } 469 | 470 | /** 471 | * Returns custom icon (if exists) 472 | * @param ctx app's context 473 | * @return drawable when custom icon exists, null otherwise 474 | */ 475 | public Drawable getCurrentCustomIcon(Context ctx) { 476 | if (hasCustomIcon()) { 477 | List items = Arrays.asList(iconUri.split("\\$")); 478 | String type = items.get(0); 479 | if (type.equals("iconpack") && items.size() == 3) { 480 | String packageName = items.get(1); 481 | String iconName = items.get(2); 482 | return DUActionUtils.getDrawable(ctx, iconName, packageName); 483 | } else if (type.equals("image") && items.size() == 2) { 484 | String uri = items.get(1); 485 | return DUActionUtils.getDrawable(ctx, Uri.parse(uri)); 486 | } 487 | } 488 | return null; 489 | } 490 | 491 | public Drawable getCurrentIcon(Context ctx) { 492 | 493 | Drawable drawable = getCurrentCustomIcon(ctx); 494 | 495 | //If icon doesn't exist (or is not set) fallback to action one 496 | if (drawable == null) { 497 | drawable = DUActionUtils.getDrawableForAction(ctx, action); 498 | } 499 | 500 | return drawable; 501 | 502 | } 503 | 504 | public boolean hasNoAction() { 505 | return TextUtils.equals(action, ActionHandler.SYSTEMUI_TASK_NO_ACTION) 506 | || TextUtils.equals(action, ActionConstants.EMPTY); 507 | } 508 | 509 | public boolean isActionRecents() { 510 | return TextUtils.equals(action, ActionHandler.SYSTEMUI_TASK_RECENTS); 511 | } 512 | 513 | @Override 514 | public int compareTo(ActionConfig another) { 515 | int result = label.toString().compareToIgnoreCase(another.label.toString()); 516 | return result; 517 | } 518 | 519 | @Override 520 | public String toDelimitedString() { 521 | return action + ActionConstants.ACTION_DELIMITER 522 | + label + ActionConstants.ACTION_DELIMITER 523 | + iconUri + ActionConstants.ACTION_DELIMITER; 524 | } 525 | 526 | @Override 527 | public void fromList(Context ctx, List items) { 528 | ArrayList actionStrings = new ArrayList(); 529 | actionStrings.addAll(items); 530 | action = items.get(0); 531 | label = DUActionUtils.getFriendlyNameForUri(ctx, action); 532 | iconUri = items.get(2); 533 | } 534 | 535 | @Override 536 | public int describeContents() { 537 | return 0; 538 | } 539 | 540 | @Override 541 | public void writeToParcel(Parcel dest, int flags) { 542 | dest.writeString(action); 543 | dest.writeString(label); 544 | dest.writeString(iconUri); 545 | } 546 | 547 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 548 | public ActionConfig createFromParcel(Parcel in) { 549 | return new ActionConfig(in); 550 | } 551 | 552 | public ActionConfig[] newArray(int size) { 553 | return new ActionConfig[size]; 554 | } 555 | }; 556 | 557 | private ActionConfig(Parcel in) { 558 | action = in.readString(); 559 | label = in.readString(); 560 | iconUri = in.readString(); 561 | } 562 | } 563 | } 564 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/DUActionUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 The TeamEos Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * Helper functions mostly for device configuration and some utilities 17 | * including a fun ViewGroup crawler and dpi conversion 18 | * 19 | */ 20 | 21 | package com.android.internal.utils.du; 22 | 23 | import android.bluetooth.BluetoothAdapter; 24 | import android.content.Context; 25 | import android.content.Intent; 26 | import android.content.pm.ActivityInfo; 27 | import android.content.pm.PackageManager; 28 | import android.content.res.Configuration; 29 | import android.content.res.Resources; 30 | import android.graphics.Bitmap; 31 | import android.graphics.BitmapFactory; 32 | import android.graphics.Matrix; 33 | //import android.content.res.ThemeConfig; 34 | import android.graphics.Color; 35 | import android.graphics.drawable.BitmapDrawable; 36 | import android.graphics.drawable.Drawable; 37 | import android.hardware.Sensor; 38 | import android.hardware.SensorManager; 39 | import android.hardware.camera2.CameraAccessException; 40 | import android.hardware.camera2.CameraCharacteristics; 41 | import android.hardware.camera2.CameraManager; 42 | import android.net.ConnectivityManager; 43 | import android.net.Uri; 44 | import android.os.Bundle; 45 | import android.os.ServiceManager; 46 | import android.os.SystemProperties; 47 | import android.telephony.TelephonyManager; 48 | import android.text.TextUtils; 49 | import android.util.DisplayMetrics; 50 | import android.util.TypedValue; 51 | import android.view.Display; 52 | import android.view.IWindowManager; 53 | import android.view.View; 54 | import android.view.ViewGroup; 55 | import android.view.WindowManager; 56 | import android.view.WindowManagerGlobal; 57 | 58 | import java.io.FileNotFoundException; 59 | import java.io.IOException; 60 | import java.io.InputStream; 61 | import java.net.URISyntaxException; 62 | import java.util.ArrayList; 63 | 64 | import com.android.internal.telephony.PhoneConstants; 65 | import com.android.internal.utils.du.ActionConstants.Defaults; 66 | import com.android.internal.utils.du.Config.ActionConfig; 67 | import com.android.internal.utils.du.Config.ButtonConfig; 68 | 69 | public final class DUActionUtils { 70 | public static final String ANDROIDNS = "http://schemas.android.com/apk/res/android"; 71 | public static final String PACKAGE_SYSTEMUI = "com.android.systemui"; 72 | public static final String PACKAGE_ANDROID = "android"; 73 | public static final String FORMAT_NONE = "none"; 74 | public static final String FORMAT_FLOAT = "float"; 75 | 76 | public static final String ID = "id"; 77 | public static final String DIMEN = "dimen"; 78 | public static final String DIMEN_PIXEL = "dimen_pixel"; 79 | public static final String FLOAT = "float"; 80 | public static final String INT = "integer"; 81 | public static final String DRAWABLE = "drawable"; 82 | public static final String COLOR = "color"; 83 | public static final String BOOL = "bool"; 84 | public static final String STRING = "string"; 85 | public static final String ANIM = "anim"; 86 | 87 | public static final int DUI_ICON_MAX_WIDTH = 512; 88 | public static final int DUI_ICON_MAX_HEIGHT = 512; 89 | 90 | // 10 inch tablets 91 | public static boolean isXLargeScreen() { 92 | int screenLayout = Resources.getSystem().getConfiguration().screenLayout & 93 | Configuration.SCREENLAYOUT_SIZE_MASK; 94 | return screenLayout == Configuration.SCREENLAYOUT_SIZE_XLARGE; 95 | } 96 | 97 | // 7 inch "phablets" i.e. grouper 98 | public static boolean isLargeScreen() { 99 | int screenLayout = Resources.getSystem().getConfiguration().screenLayout & 100 | Configuration.SCREENLAYOUT_SIZE_MASK; 101 | return screenLayout == Configuration.SCREENLAYOUT_SIZE_LARGE; 102 | } 103 | 104 | // normal phones 105 | public static boolean isNormalScreen() { 106 | int screenLayout = Resources.getSystem().getConfiguration().screenLayout & 107 | Configuration.SCREENLAYOUT_SIZE_MASK; 108 | return screenLayout == Configuration.SCREENLAYOUT_SIZE_NORMAL; 109 | } 110 | 111 | public static boolean isLandscape(Context context) { 112 | return Configuration.ORIENTATION_LANDSCAPE 113 | == context.getResources().getConfiguration().orientation; 114 | } 115 | 116 | public static boolean navigationBarCanMove() { 117 | return Resources.getSystem().getConfiguration().smallestScreenWidthDp < 600; 118 | } 119 | 120 | public static boolean hasNavbarByDefault(Context context) { 121 | boolean needsNav = (Boolean)getValue(context, "config_showNavigationBar", BOOL, PACKAGE_ANDROID); 122 | String navBarOverride = SystemProperties.get("qemu.hw.mainkeys"); 123 | if ("1".equals(navBarOverride)) { 124 | needsNav = false; 125 | } else if ("0".equals(navBarOverride)) { 126 | needsNav = true; 127 | } 128 | return needsNav; 129 | } 130 | 131 | public static boolean deviceSupportsLte(Context ctx) { 132 | final TelephonyManager tm = (TelephonyManager) 133 | ctx.getSystemService(Context.TELEPHONY_SERVICE); 134 | // return (tm.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) 135 | // || tm.getLteOnGsmMode() != 0; 136 | return tm.getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE; 137 | } 138 | 139 | public static boolean deviceSupportsDdsSupported(Context context) { 140 | TelephonyManager tm = (TelephonyManager) 141 | context.getSystemService(Context.TELEPHONY_SERVICE); 142 | return tm.isMultiSimEnabled() 143 | && tm.getMultiSimConfiguration() == TelephonyManager.MultiSimVariants.DSDA; 144 | } 145 | 146 | public static boolean deviceSupportsMobileData(Context ctx) { 147 | ConnectivityManager cm = (ConnectivityManager) ctx.getSystemService( 148 | Context.CONNECTIVITY_SERVICE); 149 | return cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); 150 | } 151 | 152 | public static boolean deviceSupportsBluetooth() { 153 | return BluetoothAdapter.getDefaultAdapter() != null; 154 | } 155 | 156 | public static boolean deviceSupportsNfc(Context context) { 157 | PackageManager packageManager = context.getPackageManager(); 158 | return packageManager.hasSystemFeature(PackageManager.FEATURE_NFC); 159 | } 160 | 161 | public static boolean deviceSupportsFlashLight(Context context) { 162 | CameraManager cameraManager = (CameraManager) context.getSystemService( 163 | Context.CAMERA_SERVICE); 164 | try { 165 | String[] ids = cameraManager.getCameraIdList(); 166 | for (String id : ids) { 167 | CameraCharacteristics c = cameraManager.getCameraCharacteristics(id); 168 | Boolean flashAvailable = c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); 169 | Integer lensFacing = c.get(CameraCharacteristics.LENS_FACING); 170 | if (flashAvailable != null 171 | && flashAvailable 172 | && lensFacing != null 173 | && lensFacing == CameraCharacteristics.LENS_FACING_BACK) { 174 | return true; 175 | } 176 | } 177 | } catch (CameraAccessException | AssertionError e) { 178 | // Ignore 179 | } 180 | return false; 181 | } 182 | 183 | public static boolean deviceSupportsCompass(Context context) { 184 | SensorManager sm = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 185 | return sm.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null 186 | && sm.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null; 187 | } 188 | 189 | public static boolean deviceSupportsDoze(Context context) { 190 | String name = (String) getValue(context, "config_dozeComponent", 191 | STRING, PACKAGE_ANDROID); 192 | return !TextUtils.isEmpty(name); 193 | } 194 | 195 | /** 196 | * This method converts dp unit to equivalent pixels, depending on device 197 | * density. 198 | * 199 | * @param dp A value in dp (density independent pixels) unit. Which we need 200 | * to convert into pixels 201 | * @param context Context to get resources and device specific display 202 | * metrics 203 | * @return A float value to represent px equivalent to dp depending on 204 | * device density 205 | */ 206 | public static float convertDpToPixel(float dp, Context context) { 207 | Resources resources = context.getResources(); 208 | DisplayMetrics metrics = resources.getDisplayMetrics(); 209 | float px = dp * (metrics.densityDpi / 160f); 210 | return px; 211 | } 212 | 213 | public static int ConvertDpToPixelAsInt(float dp, Context context) { 214 | float px = convertDpToPixel(dp, context); 215 | if (px < 1) 216 | px = 1; 217 | return Math.round(px); 218 | } 219 | 220 | public static int ConvertDpToPixelAsInt(int dp, Context context) { 221 | float px = convertDpToPixel((float) dp, context); 222 | if (px < 1) 223 | px = 1; 224 | return Math.round(px); 225 | } 226 | 227 | /** 228 | * This method converts device specific pixels to density independent 229 | * pixels. 230 | * 231 | * @param px A value in px (pixels) unit. Which we need to convert into db 232 | * @param context Context to get resources and device specific display 233 | * metrics 234 | * @return A float value to represent dp equivalent to px value 235 | */ 236 | public static float convertPixelsToDp(float px, Context context) { 237 | Resources resources = context.getResources(); 238 | DisplayMetrics metrics = resources.getDisplayMetrics(); 239 | float dp = px / (metrics.densityDpi / 160f); 240 | return dp; 241 | } 242 | 243 | public static int dpToPx(Context context, int dp) { 244 | return (int) ((dp * context.getResources().getDisplayMetrics().density) + 0.5); 245 | } 246 | 247 | public static int pxToDp(Context context, int px) { 248 | return (int) ((px / context.getResources().getDisplayMetrics().density) + 0.5); 249 | } 250 | 251 | /* utility to iterate a viewgroup and return a list of child views */ 252 | public static ArrayList getAllChildren(View v) { 253 | 254 | if (!(v instanceof ViewGroup)) { 255 | ArrayList viewArrayList = new ArrayList(); 256 | viewArrayList.add(v); 257 | return viewArrayList; 258 | } 259 | 260 | ArrayList result = new ArrayList(); 261 | 262 | ViewGroup vg = (ViewGroup) v; 263 | for (int i = 0; i < vg.getChildCount(); i++) { 264 | 265 | View child = vg.getChildAt(i); 266 | 267 | ArrayList viewArrayList = new ArrayList(); 268 | viewArrayList.add(v); 269 | viewArrayList.addAll(getAllChildren(child)); 270 | 271 | result.addAll(viewArrayList); 272 | } 273 | return result; 274 | } 275 | 276 | /* utility to iterate a viewgroup and return a list of child views of type */ 277 | public static ArrayList getAllChildren(View root, Class returnType) { 278 | if (!(root instanceof ViewGroup)) { 279 | ArrayList viewArrayList = new ArrayList(); 280 | try { 281 | viewArrayList.add(returnType.cast(root)); 282 | } catch (Exception e) { 283 | // handle all exceptions the same and silently fail 284 | } 285 | return viewArrayList; 286 | } 287 | ArrayList result = new ArrayList(); 288 | ViewGroup vg = (ViewGroup) root; 289 | for (int i = 0; i < vg.getChildCount(); i++) { 290 | View child = vg.getChildAt(i); 291 | ArrayList viewArrayList = new ArrayList(); 292 | try { 293 | viewArrayList.add(returnType.cast(root)); 294 | } catch (Exception e) { 295 | // handle all exceptions the same and silently fail 296 | } 297 | viewArrayList.addAll(getAllChildren(child, returnType)); 298 | result.addAll(viewArrayList); 299 | } 300 | return result; 301 | } 302 | 303 | public static void resolveAndUpdateButtonActions(Context ctx, Defaults defaults) { 304 | if (ctx == null || defaults == null) { 305 | return; 306 | } 307 | boolean configChanged = false; 308 | final PackageManager pm = ctx.getPackageManager(); 309 | ArrayList configs = Config.getConfig(ctx, defaults); 310 | ArrayList buttonsToChange = new ArrayList(); 311 | buttonsToChange.addAll(configs); 312 | for (int h = 0; h < configs.size(); h++) { 313 | ButtonConfig button = configs.get(h); 314 | for (int i = 0; i < 3; i++) { 315 | ActionConfig action = button.getActionConfig(i); 316 | final String task = action.getAction(); 317 | if (task.startsWith(ActionHandler.SYSTEM_PREFIX)) { 318 | continue; 319 | } 320 | String resolvedName = getFriendlyNameForUri(ctx, task); 321 | if (resolvedName == null || TextUtils.equals(resolvedName, task)) { 322 | // if resolved name is null or the full raw intent string is 323 | // returned, we were unable to resolve 324 | configChanged = true; 325 | ActionConfig newAction = new ActionConfig(ctx, 326 | ActionHandler.SYSTEMUI_TASK_NO_ACTION, action.getIconUri()); 327 | ButtonConfig newButton = buttonsToChange.get(h); 328 | newButton.setActionConfig(newAction, i); 329 | buttonsToChange.remove(h); 330 | buttonsToChange.add(h, newButton); 331 | } 332 | } 333 | } 334 | if (configChanged) { 335 | Config.setConfig(ctx, defaults, buttonsToChange); 336 | } 337 | } 338 | 339 | public static Intent getIntent(String uri) { 340 | if (uri == null || uri.startsWith(ActionHandler.SYSTEM_PREFIX)) { 341 | return null; 342 | } 343 | 344 | Intent intent = null; 345 | try { 346 | intent = Intent.parseUri(uri, 0); 347 | } catch (URISyntaxException e) { 348 | e.printStackTrace(); 349 | } 350 | return intent; 351 | } 352 | 353 | public static Object getValue(Context context, String resName, String resType, String pkg) { 354 | return getValue(context, resName, resType, null, pkg); 355 | } 356 | 357 | public static Object getValue(Context context, String resName, String resType, String format, 358 | String pkg) { 359 | Resources res = getResourcesForPackage(context, pkg); 360 | String tmp; 361 | if (resType.equals(DIMEN_PIXEL)) { 362 | tmp = DIMEN; 363 | } else { 364 | tmp = resType; 365 | } 366 | int id = res.getIdentifier(resName, tmp, pkg); 367 | if (format != null) { // standard res 368 | TypedValue typedVal = new TypedValue(); 369 | res.getValue(id, typedVal, true); 370 | if (format.equals(FORMAT_FLOAT)) { 371 | return Float.valueOf(typedVal.getFloat()); 372 | } 373 | } else { // typed values 374 | if (resType.equals(ID)) { 375 | return Integer.valueOf(id); 376 | } else if (resType.equals(DIMEN)) { 377 | return Float.valueOf(res.getDimension(id)); 378 | } else if (resType.equals(DIMEN_PIXEL)) { 379 | return Integer.valueOf(res.getDimensionPixelSize(id)); 380 | } else if (resType.equals(FLOAT)) { 381 | return Float.valueOf(res.getFloat(id)); 382 | } else if (resType.equals(INT)) { 383 | return Integer.valueOf(res.getInteger(id)); 384 | } else if (resType.equals(COLOR)) { 385 | int rawColor = res.getColor(id); 386 | return Integer.valueOf(Color.argb(Color.alpha(rawColor), Color.red(rawColor), 387 | Color.green(rawColor), Color.blue(rawColor))); 388 | } else if (resType.equals(BOOL)) { 389 | return Boolean.valueOf(res.getBoolean(id)); 390 | } else if (resType.equals(STRING)) { 391 | return String.valueOf(res.getString(id)); 392 | } else if (resType.equals(DRAWABLE)) { 393 | return getDrawable(context, resName, pkg); 394 | } 395 | } 396 | return null; 397 | } 398 | 399 | public static void putValue(String key, Object val, String type, Bundle b) { 400 | if (type.equals(ID) || type.equals(DIMEN_PIXEL) || type.equals(INT) || type.equals(COLOR)) { 401 | b.putInt(key, (Integer) val); 402 | } else if (type.equals(FLOAT) || type.equals(DIMEN)) { 403 | b.putFloat(key, (Float) val); 404 | } else if (type.equals(BOOL)) { 405 | b.putBoolean(key, (Boolean) val); 406 | } else if (type.equals(STRING)) { 407 | b.putString(key, (String) val); 408 | } 409 | } 410 | 411 | public static int getIdentifier(Context context, String resName, String resType, String pkg) { 412 | try { 413 | Resources res = context.getPackageManager() 414 | .getResourcesForApplication(pkg); 415 | int ident = res.getIdentifier(resName, resType, pkg); 416 | return ident; 417 | } catch (Exception e) { 418 | return -1; 419 | } 420 | } 421 | 422 | public static String getString(Context context, String resName, String pkg) { 423 | return (String) getValue(context, resName, STRING, null, pkg); 424 | } 425 | 426 | public static boolean getBoolean(Context context, String resName, String pkg) { 427 | return (Boolean) getValue(context, resName, BOOL, null, pkg); 428 | } 429 | 430 | public static int getInt(Context context, String resName, String pkg) { 431 | return (Integer) getValue(context, resName, INT, null, pkg); 432 | } 433 | 434 | public static int getColor(Context context, String resName, String pkg) { 435 | return (Integer) getValue(context, resName, COLOR, null, pkg); 436 | } 437 | 438 | public static int getId(Context context, String resName, String pkg) { 439 | return (Integer) getValue(context, resName, ID, null, pkg); 440 | } 441 | 442 | public static float getDimen(Context context, String resName, String pkg) { 443 | return (Float) getValue(context, resName, DIMEN, null, pkg); 444 | } 445 | 446 | public static int getDimenPixelSize(Context context, String resName, String pkg) { 447 | return (Integer) getValue(context, resName, DIMEN_PIXEL, null, pkg); 448 | } 449 | 450 | public static Drawable getDrawable(Context context, String drawableName, String pkg) { 451 | return getDrawable(getResourcesForPackage(context, pkg), drawableName, pkg); 452 | } 453 | 454 | public static Drawable getDrawable(Context context, Uri uri) { 455 | //set inputs here so we can clean up them in the finally 456 | InputStream inputStream = null; 457 | 458 | try { 459 | //get the inputstream 460 | inputStream = context.getContentResolver().openInputStream(uri); 461 | 462 | //get available bitmapfactory options 463 | BitmapFactory.Options options = new BitmapFactory.Options(); 464 | //query the bitmap to decode the stream but don't allocate pixels in memory yet 465 | options.inJustDecodeBounds = true; 466 | //decode the bitmap with calculated bounds 467 | Bitmap b1 = BitmapFactory.decodeStream(inputStream, null, options); 468 | //get raw height and width of the bitmap 469 | int rawHeight = options.outHeight; 470 | int rawWidth = options.outWidth; 471 | 472 | //check if the bitmap is big and we need to scale the quality to take less memory 473 | options.inSampleSize = calculateInSampleSize(options, rawHeight, rawWidth); 474 | 475 | //We need to close and load again the inputstream to avoid null 476 | try { 477 | inputStream.close(); 478 | } 479 | catch (IOException e) { 480 | e.printStackTrace(); 481 | } 482 | inputStream = context.getContentResolver().openInputStream(uri); 483 | 484 | //decode the stream again, with the calculated SampleSize option, 485 | //and allocate the memory. Also add some metrics options to take a proper density 486 | options.inJustDecodeBounds = false; 487 | DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 488 | options.inScreenDensity = metrics.densityDpi; 489 | options.inTargetDensity = metrics.densityDpi; 490 | options.inDensity = DisplayMetrics.DENSITY_DEFAULT; 491 | b1 = BitmapFactory.decodeStream(inputStream, null, options); 492 | return new BitmapDrawable(context.getResources(), b1); 493 | 494 | } catch (FileNotFoundException e) { 495 | e.printStackTrace(); 496 | return null; 497 | //clean up the system resources 498 | } finally { 499 | if (inputStream != null) { 500 | try { 501 | inputStream.close(); 502 | } 503 | catch (IOException e) { 504 | e.printStackTrace(); 505 | } 506 | } 507 | } 508 | } 509 | 510 | //Automate the quality scaling process 511 | public static int calculateInSampleSize(BitmapFactory.Options options, int height, int width) { 512 | //set default inSampleSize scale factor (no scaling) 513 | int inSampleSize = 1; 514 | 515 | //if img size is in 257-512 range, sample scale factor will be 4x 516 | if (height > 256 || width > 256) { 517 | inSampleSize = 4; 518 | return inSampleSize; 519 | //if img size is in 129-256 range, sample scale factor will be 2x 520 | } else if (height > 128 || width > 128) { 521 | inSampleSize = 2; 522 | return inSampleSize; 523 | } 524 | //if img size is in 0-128 range, no need to scale it 525 | return inSampleSize; 526 | } 527 | 528 | /** 529 | * Screen images based on desired dimensions before fully decoding 530 | * 531 | *@param ctx Calling context 532 | *@param uri Image uri 533 | *@param maxWidth maximum allowed image width 534 | *@param maxHeight maximum allowed image height 535 | */ 536 | public static boolean isBitmapAllowedSize(Context ctx, Uri uri, int maxWidth, int maxHeight) { 537 | InputStream inputStream = null; 538 | try { 539 | inputStream = ctx.getContentResolver().openInputStream(uri); 540 | BitmapFactory.Options options = new BitmapFactory.Options(); 541 | options.inJustDecodeBounds = true; 542 | BitmapFactory.decodeStream(inputStream, null, options); 543 | if (options.outWidth <= maxWidth && options.outHeight <= maxHeight) { 544 | return true; 545 | } 546 | } catch (Exception e) { 547 | return false; 548 | } finally { 549 | try { 550 | inputStream.close(); 551 | } 552 | catch (IOException e) { 553 | e.printStackTrace(); 554 | } 555 | } 556 | return false; 557 | } 558 | 559 | public static Drawable getDrawableFromComponent(PackageManager pm, String activity) { 560 | Drawable d = null; 561 | try { 562 | Intent intent = Intent.parseUri(activity, 0); 563 | ActivityInfo info = intent.resolveActivityInfo(pm, 564 | PackageManager.GET_ACTIVITIES); 565 | if (info != null) { 566 | d = info.loadIcon(pm); 567 | } 568 | } catch (Exception e) { 569 | e.printStackTrace(); 570 | } 571 | return d; 572 | } 573 | 574 | public static String getFriendlyActivityName(PackageManager pm, Intent intent, 575 | boolean labelOnly) { 576 | ActivityInfo ai = intent.resolveActivityInfo(pm, PackageManager.GET_ACTIVITIES); 577 | String friendlyName = null; 578 | if (ai != null) { 579 | friendlyName = ai.loadLabel(pm).toString(); 580 | if (friendlyName == null && !labelOnly) { 581 | friendlyName = ai.name; 582 | } 583 | } 584 | return friendlyName != null || labelOnly ? friendlyName : intent.toUri(0); 585 | } 586 | 587 | public static String getFriendlyShortcutName(PackageManager pm, Intent intent) { 588 | String activityName = getFriendlyActivityName(pm, intent, true); 589 | String name = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); 590 | 591 | if (activityName != null && name != null) { 592 | return activityName + ": " + name; 593 | } 594 | return name != null ? name : intent.toUri(0); 595 | } 596 | 597 | public static String getFriendlyNameForUri(Context ctx, String uri) { 598 | if (uri == null) { 599 | return null; 600 | } 601 | if (uri.startsWith(ActionHandler.SYSTEM_PREFIX)) { 602 | for (int i = 0; i < ActionHandler.systemActions.length; i++) { 603 | if (ActionHandler.systemActions[i].mAction.equals(uri)) { 604 | return getString(ctx, ActionHandler.systemActions[i].mLabelRes, 605 | ActionHandler.systemActions[i].mResPackage); 606 | } 607 | } 608 | } else { 609 | try { 610 | Intent intent = Intent.parseUri(uri, 0); 611 | if (Intent.ACTION_MAIN.equals(intent.getAction())) { 612 | return getFriendlyActivityName(ctx.getPackageManager(), intent, false); 613 | } 614 | return getFriendlyShortcutName(ctx.getPackageManager(), intent); 615 | } catch (URISyntaxException e) { 616 | } 617 | } 618 | return uri; 619 | } 620 | 621 | /** 622 | * 623 | * @param Target package resources 624 | * @param drawableName 625 | * @param Target package name 626 | * @return the drawable if found, otherwise fall back to a green android guy 627 | */ 628 | public static Drawable getDrawable(Resources res, String drawableName, String pkg) { 629 | try { 630 | int resId = res.getIdentifier(drawableName, DRAWABLE, pkg); 631 | Drawable icon = ImageHelper.getVector(res, resId, false); 632 | if (icon == null) { 633 | icon = res.getDrawable(resId); 634 | } 635 | return icon; 636 | } catch (Exception e) { 637 | return res.getDrawable( 638 | com.android.internal.R.drawable.sym_def_app_icon); 639 | } 640 | } 641 | 642 | /** 643 | * 644 | * @param Target package resources 645 | * @param drawableName 646 | * @param Target package name 647 | * @return the drawable if found, null otherwise. Useful for testing if a drawable is found 648 | * in a theme overlay 649 | */ 650 | private static Drawable getMaybeNullDrawable(Resources res, String drawableName, String pkg) { 651 | try { 652 | int resId = res.getIdentifier(drawableName, DRAWABLE, pkg); 653 | Drawable icon = ImageHelper.getVector(res, resId, false); 654 | if (icon == null) { 655 | icon = res.getDrawable(resId); 656 | } 657 | return icon; 658 | } catch (Exception e) { 659 | return null; 660 | } 661 | } 662 | 663 | public static Resources getResourcesForPackage(Context ctx, String pkg) { 664 | try { 665 | Resources res = ctx.getPackageManager() 666 | .getResourcesForApplication(pkg); 667 | return res; 668 | } catch (Exception e) { 669 | return ctx.getResources(); 670 | } 671 | } 672 | 673 | /** 674 | * 675 | * @param Context of the calling package 676 | * @param the action we want a drawable for 677 | * @return if a system action drawable is requested, we try to get the drawable 678 | * from any current navigation overlay. if no overlay is found, get it 679 | * from SystemUI. Return a component drawable if not a system action 680 | */ 681 | public static Drawable getDrawableForAction(Context context, String action) { 682 | Drawable d = null; 683 | 684 | // this null check is probably no-op but let's be safe anyways 685 | if (action == null || context == null) { 686 | return d; 687 | } 688 | if (action.startsWith(ActionHandler.SYSTEM_PREFIX)) { 689 | for (int i = 0; i < ActionHandler.systemActions.length; i++) { 690 | if (ActionHandler.systemActions[i].mAction.equals(action)) { 691 | // should always be SystemUI 692 | String packageName = ActionHandler.systemActions[i].mResPackage; 693 | Resources res = getResourcesForPackage(context, packageName); 694 | String iconName = ActionHandler.systemActions[i].mIconRes; 695 | d = getNavbarThemedDrawable(context, res, iconName); 696 | if (d == null) { 697 | d = getDrawable(res, iconName, packageName); 698 | } 699 | } 700 | } 701 | } else { 702 | d = getDrawableFromComponent(context.getPackageManager(), action); 703 | } 704 | return d; 705 | } 706 | 707 | /** 708 | * 709 | * @param calling package context, usually Settings for the custom action list adapter 710 | * @param target package resources, usually SystemUI 711 | * @param drawableName 712 | * @return a navigation bar overlay themed action drawable if available, otherwise 713 | * return drawable from SystemUI resources 714 | */ 715 | public static Drawable getNavbarThemedDrawable(Context context, Resources defRes, 716 | String drawableName) { 717 | if (context == null || defRes == null || drawableName == null) 718 | return null; 719 | 720 | // TODO: turn on cmte support when it comes back 721 | return getDrawable(defRes, drawableName, PACKAGE_SYSTEMUI); 722 | /* 723 | ThemeConfig themeConfig = context.getResources().getConfiguration().themeConfig; 724 | 725 | Drawable d = null; 726 | if (themeConfig != null) { 727 | try { 728 | final String navbarThemePkgName = themeConfig.getOverlayForNavBar(); 729 | final String sysuiThemePkgName = themeConfig.getOverlayForStatusBar(); 730 | // Check if the same theme is applied for systemui, if so we can skip this 731 | if (navbarThemePkgName != null && !navbarThemePkgName.equals(sysuiThemePkgName)) { 732 | // Navbar theme and SystemUI (statusbar) theme packages are different 733 | // But we can't assume navbar package has our drawable, so try navbar theme 734 | // package first. If we fail, try the systemui (statusbar) package 735 | // if we still fail, fall back to default package resource 736 | Resources res = context.getPackageManager().getThemedResourcesForApplication( 737 | PACKAGE_SYSTEMUI, navbarThemePkgName); 738 | d = getMaybeNullDrawable(res, drawableName, PACKAGE_SYSTEMUI); 739 | if (d == null) { 740 | // drawable not found in overlay, get from default SystemUI res 741 | d = getDrawable(defRes, drawableName, PACKAGE_SYSTEMUI); 742 | } 743 | } else { 744 | // no navbar overlay present, get from default SystemUI res 745 | d = getDrawable(defRes, drawableName, PACKAGE_SYSTEMUI); 746 | } 747 | } catch (PackageManager.NameNotFoundException e) { 748 | // error thrown (unlikely), get from default SystemUI res 749 | d = getDrawable(defRes, drawableName, PACKAGE_SYSTEMUI); 750 | } 751 | } 752 | if (d == null) { 753 | // theme config likely null, get from default SystemUI res 754 | d = getDrawable(defRes, drawableName, PACKAGE_SYSTEMUI); 755 | } 756 | return d; 757 | */ 758 | } 759 | } 760 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/ActionConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 TeamEos project 3 | * Author Randall Rushing aka bigrushdog, randall.rushing@gmail.com 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * ActionConstants.java: A helper class to assist Config.java with loading 18 | * and assigning default feature configurations. Nested classes implement 19 | * the static interface Defaults, which allows Settings and Config.java 20 | * to handle configurations in a non-implementation specific way, allowing 21 | * for more generalized code structures. 22 | * 23 | * Of strong importance is the ConfigMap pojo class. Current settings use 24 | * a ActionPreference which sets a single action. Therefore, we must have a 25 | * way to map individual actions to their associated buttons. ActionPreference 26 | * key MUST match the tag associated with the target ConfigMap. 27 | * 28 | */ 29 | 30 | package com.android.internal.utils.du; 31 | 32 | import java.util.HashMap; 33 | import java.util.Map; 34 | 35 | import com.android.internal.utils.du.ActionHandler.SystemAction; 36 | import com.android.internal.utils.du.Config.ActionConfig; 37 | 38 | import android.content.Context; 39 | import android.content.res.Resources; 40 | import android.os.Bundle; 41 | import android.provider.Settings; 42 | import android.util.Log; 43 | import android.util.TypedValue; 44 | 45 | public class ActionConstants { 46 | public static interface Defaults { 47 | public int getConfigType(); 48 | public String getUri(); 49 | public String getDefaultConfig(); 50 | public int getMaxButtons(); 51 | public Map getActionMap(); 52 | public Bundle getConfigs(Context context); 53 | } 54 | 55 | public static final String ACTION_DELIMITER = "|"; 56 | public static final String EMPTY = "empty"; 57 | public static final int SMARTBAR = 1; 58 | public static final int HWKEYS = 2; 59 | public static final int FLING = 3; 60 | public static final int PIE_PRIMARY = 4; 61 | public static final int PIE_SECONDARY = 5; 62 | 63 | private static final Smartbar smartbar = new Smartbar(); 64 | private static final Hwkeys hwkeys = new Hwkeys(); 65 | private static final Fling fling = new Fling(); 66 | private static final PiePrimary pie_primary = new PiePrimary(); 67 | private static final PieSecond pie_second = new PieSecond(); 68 | 69 | public static Defaults getDefaults(int type) { 70 | if (type == SMARTBAR) { 71 | return smartbar; 72 | } else if (type == HWKEYS) { 73 | return hwkeys; 74 | } else if (type == FLING) { 75 | return fling; 76 | } else if (type == PIE_PRIMARY){ 77 | return pie_primary; 78 | } else if (type == PIE_SECONDARY) { 79 | return pie_second; 80 | } else { 81 | return null; 82 | } 83 | } 84 | 85 | public static String dl(String s) { 86 | return s + ACTION_DELIMITER; 87 | } 88 | 89 | public static class Smartbar implements Defaults { 90 | public static final int SMARTBAR_MAX_BUTTONS = 10; 91 | public static final String SMARTBAR_DEF_BUTTONS = "3"; 92 | public static final String BUTTON1_TAG = "smartbar_button_1"; 93 | public static final String BUTTON2_TAG = "smartbar_button_2"; 94 | public static final String BUTTON3_TAG = "smartbar_button_3"; 95 | public static final String BUTTON4_TAG = "smartbar_button_4"; 96 | public static final String BUTTON5_TAG = "smartbar_button_5"; 97 | public static final String BUTTON6_TAG = "smartbar_button_6"; 98 | public static final String BUTTON7_TAG = "smartbar_button_7"; 99 | 100 | public static final String SMARTBAR_CONFIG_DEFAULT = 101 | dl(SMARTBAR_DEF_BUTTONS) // default number of ButtonConfig 102 | + dl(BUTTON1_TAG) // button tag 103 | + dl(SystemAction.Back.mAction) + dl(SystemAction.Back.mLabelRes) + dl(EMPTY) // single tap (PRIMARY) 104 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // long press (SECOND) 105 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // double tap (THIRD) 106 | 107 | + dl(BUTTON2_TAG) 108 | + dl(SystemAction.Home.mAction) + dl(SystemAction.Home.mLabelRes) + dl(EMPTY) 109 | + dl(SystemAction.GoogleNowOnTap.mAction) + dl(SystemAction.GoogleNowOnTap.mLabelRes) + dl(EMPTY) 110 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 111 | 112 | + dl(BUTTON3_TAG) 113 | + dl(SystemAction.Overview.mAction) + dl(SystemAction.Overview.mLabelRes) + dl(EMPTY) 114 | + dl(SystemAction.SplitScreen.mAction) + dl(SystemAction.SplitScreen.mLabelRes) + dl(EMPTY) 115 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + EMPTY; 116 | /* 117 | + dl(BUTTON4_TAG) 118 | + dl(SystemAction.ExpandedDesktop.mAction) + dl(SystemAction.ExpandedDesktop.mLabelRes) + dl(EMPTY) 119 | + dl(SystemAction.Flashlight.mAction) + dl(SystemAction.Flashlight.mLabelRes) + dl(EMPTY) 120 | + dl(SystemAction.PowerMenu.mAction) + dl(SystemAction.PowerMenu.mLabelRes) + dl(EMPTY) 121 | 122 | + dl(BUTTON5_TAG) 123 | + dl(SystemAction.Screenrecord.mAction) + dl(SystemAction.Screenrecord.mLabelRes) + dl(EMPTY) 124 | + dl(SystemAction.KillApp.mAction) + dl(SystemAction.KillApp.mLabelRes) + dl(EMPTY) 125 | + dl(SystemAction.ScreenOff.mAction) + dl(SystemAction.ScreenOff.mLabelRes) + EMPTY; 126 | */ 127 | @Override 128 | public String getUri() { 129 | return "smartbar_button_config"; 130 | } 131 | 132 | @Override 133 | public String getDefaultConfig() { 134 | return SMARTBAR_CONFIG_DEFAULT; 135 | } 136 | 137 | @Override 138 | public int getMaxButtons() { 139 | return SMARTBAR_MAX_BUTTONS; 140 | } 141 | 142 | @Override 143 | public int getConfigType() { 144 | return SMARTBAR; 145 | } 146 | 147 | @Override 148 | public Map getActionMap() { 149 | return null; 150 | } 151 | 152 | @Override 153 | public Bundle getConfigs(Context context) { 154 | // TODO Auto-generated method stub 155 | return null; 156 | } 157 | } 158 | 159 | public static class Hwkeys implements Defaults { 160 | public static final int HWKEY_MAX_BUTTONS = 7; 161 | public static final String HWKEY_DEF_BUTTONS = "5"; 162 | public static final String BACK_BUTTON_TAG = "hwkeys_button_back"; 163 | public static final String HOME_BUTTON_TAG = "hwkeys_button_home"; 164 | public static final String OVERVIEW_BUTTON_TAG = "hwkeys_button_overview"; 165 | public static final String MENU_BUTTON_TAG = "hwkeys_button_menu"; 166 | public static final String ASSIST_BUTTON_TAG = "hwkeys_button_assist"; 167 | public static final String EXTRA1_BUTTON_TAG = "hwkeys_button_camera"; 168 | public static final String EXTRA2_BUTTON_TAG = "hwkeys_button_extra"; 169 | 170 | public static final String BACK_BUTTON_SINGLE_TAP_TAG = "hwkeys_button_back_single_tap"; 171 | public static final String HOME_BUTTON_SINGLE_TAP_TAG = "hwkeys_button_home_single_tap"; 172 | public static final String OVERVIEW_BUTTON_SINGLE_TAP_TAG = "hwkeys_button_overview_single_tap"; 173 | public static final String MENU_BUTTON_SINGLE_TAP_TAG = "hwkeys_button_menu_single_tap"; 174 | public static final String ASSIST_BUTTON_SINGLE_TAP_TAG = "hwkeys_button_assist_single_tap"; 175 | 176 | public static final String BACK_BUTTON_LONG_PRESS_TAG = "hwkeys_button_back_long_press"; 177 | public static final String HOME_BUTTON_LONG_PRESS_TAG = "hwkeys_button_home_long_press"; 178 | public static final String OVERVIEW_BUTTON_LONG_PRESS_TAG = "hwkeys_button_overview_long_press"; 179 | public static final String MENU_BUTTON_LONG_PRESS_TAG = "hwkeys_button_menu_long_press"; 180 | public static final String ASSIST_BUTTON_LONG_PRESS_TAG = "hwkeys_button_assist_long_press"; 181 | 182 | public static final String BACK_BUTTON_DOUBLE_TAP_TAG = "hwkeys_button_back_double_tap"; 183 | public static final String HOME_BUTTON_DOUBLE_TAP_TAG = "hwkeys_button_home_double_tap"; 184 | public static final String OVERVIEW_BUTTON_DOUBLE_TAP_TAG = "hwkeys_button_overview_double_tap"; 185 | public static final String MENU_BUTTON_DOUBLE_TAP_TAG = "hwkeys_button_menu_double_tap"; 186 | public static final String ASSIST_BUTTON_DOUBLE_TAP_TAG = "hwkeys_button_assist_double_tap"; 187 | 188 | private static final Map configMap = new HashMap(); 189 | 190 | static { 191 | configMap.put(BACK_BUTTON_SINGLE_TAP_TAG, new ConfigMap(0, ActionConfig.PRIMARY)); 192 | configMap.put(HOME_BUTTON_SINGLE_TAP_TAG, new ConfigMap(1, ActionConfig.PRIMARY)); 193 | configMap.put(OVERVIEW_BUTTON_SINGLE_TAP_TAG, new ConfigMap(2, ActionConfig.PRIMARY)); 194 | configMap.put(MENU_BUTTON_SINGLE_TAP_TAG, new ConfigMap(3, ActionConfig.PRIMARY)); 195 | configMap.put(ASSIST_BUTTON_SINGLE_TAP_TAG, new ConfigMap(4, ActionConfig.PRIMARY)); 196 | configMap.put(BACK_BUTTON_LONG_PRESS_TAG, new ConfigMap(0, ActionConfig.SECOND)); 197 | configMap.put(HOME_BUTTON_LONG_PRESS_TAG, new ConfigMap(1, ActionConfig.SECOND)); 198 | configMap.put(OVERVIEW_BUTTON_LONG_PRESS_TAG, new ConfigMap(2, ActionConfig.SECOND)); 199 | configMap.put(MENU_BUTTON_LONG_PRESS_TAG, new ConfigMap(3, ActionConfig.SECOND)); 200 | configMap.put(ASSIST_BUTTON_LONG_PRESS_TAG, new ConfigMap(4, ActionConfig.SECOND)); 201 | configMap.put(BACK_BUTTON_DOUBLE_TAP_TAG, new ConfigMap(0, ActionConfig.THIRD)); 202 | configMap.put(HOME_BUTTON_DOUBLE_TAP_TAG, new ConfigMap(1, ActionConfig.THIRD)); 203 | configMap.put(OVERVIEW_BUTTON_DOUBLE_TAP_TAG, new ConfigMap(2, ActionConfig.THIRD)); 204 | configMap.put(MENU_BUTTON_DOUBLE_TAP_TAG, new ConfigMap(3, ActionConfig.THIRD)); 205 | configMap.put(ASSIST_BUTTON_DOUBLE_TAP_TAG, new ConfigMap(4, ActionConfig.THIRD)); 206 | } 207 | 208 | public static final String HWKEYS_CONFIG_DEFAULT = 209 | dl(HWKEY_DEF_BUTTONS) 210 | + dl(BACK_BUTTON_TAG) 211 | + dl(SystemAction.Back.mAction) + dl(SystemAction.Back.mLabelRes) + dl(EMPTY) // single tap (PRIMARY) 212 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // long press (SECOND) 213 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // double tap (THIRD) 214 | 215 | + dl(HOME_BUTTON_TAG) 216 | + dl(SystemAction.Home.mAction) + dl(SystemAction.Home.mLabelRes) + dl(EMPTY) 217 | + dl(SystemAction.Assistant.mAction) + dl(SystemAction.Assistant.mLabelRes) + dl(EMPTY) 218 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 219 | 220 | + dl(OVERVIEW_BUTTON_TAG) 221 | + dl(SystemAction.Overview.mAction) + dl(SystemAction.Overview.mLabelRes) + dl(EMPTY) 222 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 223 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 224 | 225 | + dl(MENU_BUTTON_TAG) 226 | + dl(SystemAction.Menu.mAction) + dl(SystemAction.Menu.mLabelRes) + dl(EMPTY) 227 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 228 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 229 | 230 | + dl(ASSIST_BUTTON_TAG) 231 | + dl(SystemAction.Assistant.mAction) + dl(SystemAction.Assistant.mLabelRes) + dl(EMPTY) 232 | + dl(SystemAction.VoiceSearch.mAction) + dl(SystemAction.VoiceSearch.mLabelRes) + dl(EMPTY) 233 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + EMPTY; 234 | 235 | @Override 236 | public int getConfigType() { 237 | return HWKEYS; 238 | } 239 | 240 | @Override 241 | public String getUri() { 242 | //return Settings.System.HWKEY_BUTTON_ACTIONS; 243 | return "hwkey_config"; 244 | } 245 | 246 | @Override 247 | public String getDefaultConfig() { 248 | return HWKEYS_CONFIG_DEFAULT; 249 | } 250 | 251 | @Override 252 | public int getMaxButtons() { 253 | return HWKEY_MAX_BUTTONS; 254 | } 255 | 256 | @Override 257 | public Map getActionMap() { 258 | return configMap; 259 | } 260 | 261 | @Override 262 | public Bundle getConfigs(Context context) { 263 | // TODO Auto-generated method stub 264 | return null; 265 | } 266 | } 267 | 268 | public static class Fling implements Defaults { 269 | public static final int FLING_MAX_BUTTONS = 10; 270 | public static final String FLING_DEF_BUTTONS = "5"; 271 | 272 | public static final String RIGHT_TAP_TAG = "fling_right_taps"; 273 | public static final String LEFT_TAP_TAG = "fling_left_taps"; 274 | public static final String RIGHT_FLING_TAG = "fling_right"; 275 | public static final String LEFT_FLING = "fling_left"; 276 | public static final String UP_FLING = "fling_up"; 277 | 278 | public static final String SINGLE_LEFT_TAP_TAG = "single_left_tap"; 279 | public static final String SINGLE_RIGHT_TAP_TAG = "single_right_tap"; 280 | public static final String DOUBLE_LEFT_TAP_TAG = "double_left_tap"; 281 | public static final String DOUBLE_RIGHT_TAP_TAG = "double_right_tap"; 282 | public static final String LONG_LEFT_PRESS_TAG = "long_left_press"; 283 | public static final String LONG_RIGHT_PRESS_TAG = "long_right_press"; 284 | public static final String FLING_SHORT_LEFT_TAG = "fling_short_left"; 285 | public static final String FLING_SHORT_RIGHT_TAG = "fling_short_right"; 286 | public static final String FLING_LONG_LEFT_TAG = "fling_long_left"; 287 | public static final String FLING_LONG_RIGHT_TAG = "fling_long_right"; 288 | public static final String FLING_RIGHT_UP_TAG = "fling_right_up"; 289 | public static final String FLING_LEFT_UP_TAG = "fling_left_up"; 290 | public static final String CONFIG_fling_touchslop_increase_factor = "config_fling_touchslop_increase_factor"; 291 | public static final String CONFIG_FlingLongSwipePortraitLeft = "config_FlingLongSwipePortraitLeft"; 292 | public static final String CONFIG_FlingLongSwipePortraitRight = "config_FlingLongSwipePortraitRight"; 293 | public static final String CONFIG_FlingLongSwipeLandscapeLeft = "config_FlingLongSwipeLandscapeLeft"; 294 | public static final String CONFIG_FlingLongSwipeLandscapeRight = "config_FlingLongSwipeLandscapeRight"; 295 | public static final String CONFIG_FlingLongSwipeVerticalUp = "config_FlingLongSwipeVerticalUp"; 296 | public static final String CONFIG_FlingLongSwipeVerticalDown = "config_FlingLongSwipeVerticalDown"; 297 | public static final String CONFIG_pulsePathEffect_1 = "config_pulsePathEffect_1"; 298 | public static final String CONFIG_pulsePathEffect_2 = "config_pulsePathEffect_2"; 299 | public static final String CONFIG_pulsePathStrokeWidth = "config_pulsePathStrokeWidth"; 300 | public static final String CONFIG_pulseFillColor = "config_pulseFillColor"; 301 | public static final String CONFIG_pulseDivisions = "config_pulseDivisions"; 302 | public static final String CONFIG_pulseDbFuzzFactor = "config_pulseDbFuzzFactor"; 303 | public static final String CONFIG_pulseDbFuzz = "config_pulseDbFuzz"; 304 | 305 | private static final Map defMap = new HashMap(); 306 | 307 | static { 308 | defMap.put(CONFIG_fling_touchslop_increase_factor, new ConfigHolder( 309 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_fling_touchslop_increase_factor, 310 | DUActionUtils.FORMAT_FLOAT, DUActionUtils.DIMEN)); 311 | defMap.put(CONFIG_FlingLongSwipePortraitLeft, new ConfigHolder( 312 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_FlingLongSwipePortraitLeft, 313 | DUActionUtils.FORMAT_FLOAT, DUActionUtils.DIMEN)); 314 | defMap.put(CONFIG_FlingLongSwipePortraitRight, new ConfigHolder( 315 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_FlingLongSwipePortraitRight, 316 | DUActionUtils.FORMAT_FLOAT, DUActionUtils.DIMEN)); 317 | defMap.put(CONFIG_FlingLongSwipeLandscapeLeft, new ConfigHolder( 318 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_FlingLongSwipeLandscapeLeft, 319 | DUActionUtils.FORMAT_FLOAT, DUActionUtils.DIMEN)); 320 | defMap.put(CONFIG_FlingLongSwipeLandscapeRight, new ConfigHolder( 321 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_FlingLongSwipeLandscapeRight, 322 | DUActionUtils.FORMAT_FLOAT, DUActionUtils.DIMEN)); 323 | defMap.put(CONFIG_FlingLongSwipeVerticalUp, new ConfigHolder( 324 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_FlingLongSwipeVerticalUp, 325 | DUActionUtils.FORMAT_FLOAT, DUActionUtils.DIMEN)); 326 | defMap.put(CONFIG_FlingLongSwipeVerticalDown, new ConfigHolder( 327 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_FlingLongSwipeVerticalDown, 328 | DUActionUtils.FORMAT_FLOAT, DUActionUtils.DIMEN)); 329 | defMap.put(CONFIG_pulsePathEffect_1, new ConfigHolder( 330 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_pulsePathEffect_1, DUActionUtils.DIMEN_PIXEL)); 331 | defMap.put(CONFIG_pulsePathEffect_2, new ConfigHolder( 332 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_pulsePathEffect_2, DUActionUtils.DIMEN_PIXEL)); 333 | defMap.put(CONFIG_pulsePathStrokeWidth, new ConfigHolder( 334 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_pulsePathStrokeWidth, DUActionUtils.DIMEN_PIXEL)); 335 | defMap.put(CONFIG_pulseFillColor, new ConfigHolder( 336 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_pulseFillColor, DUActionUtils.COLOR)); 337 | defMap.put(CONFIG_pulseDivisions, new ConfigHolder( 338 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_pulseDivisions, DUActionUtils.INT)); 339 | defMap.put(CONFIG_pulseDbFuzzFactor, new ConfigHolder( 340 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_pulseDbFuzzFactor, DUActionUtils.INT)); 341 | defMap.put(CONFIG_pulseDbFuzz, new ConfigHolder( 342 | DUActionUtils.PACKAGE_SYSTEMUI, CONFIG_pulseDbFuzz, DUActionUtils.INT)); 343 | } 344 | 345 | private static final Map configMap = new HashMap(); 346 | 347 | static { 348 | configMap.put(SINGLE_LEFT_TAP_TAG, new ConfigMap(1, ActionConfig.PRIMARY)); 349 | configMap.put(SINGLE_RIGHT_TAP_TAG, new ConfigMap(0, ActionConfig.PRIMARY)); 350 | configMap.put(DOUBLE_LEFT_TAP_TAG, new ConfigMap(1, ActionConfig.THIRD)); 351 | configMap.put(DOUBLE_RIGHT_TAP_TAG, new ConfigMap(0, ActionConfig.THIRD)); 352 | configMap.put(LONG_LEFT_PRESS_TAG, new ConfigMap(1, ActionConfig.SECOND)); 353 | configMap.put(LONG_RIGHT_PRESS_TAG, new ConfigMap(0, ActionConfig.SECOND)); 354 | configMap.put(FLING_SHORT_LEFT_TAG, new ConfigMap(3, ActionConfig.PRIMARY)); 355 | configMap.put(FLING_SHORT_RIGHT_TAG, new ConfigMap(2, ActionConfig.PRIMARY)); 356 | configMap.put(FLING_LONG_LEFT_TAG, new ConfigMap(3, ActionConfig.SECOND)); 357 | configMap.put(FLING_LONG_RIGHT_TAG, new ConfigMap(2, ActionConfig.SECOND)); 358 | configMap.put(FLING_RIGHT_UP_TAG, new ConfigMap(4, ActionConfig.PRIMARY)); 359 | configMap.put(FLING_LEFT_UP_TAG, new ConfigMap(4, ActionConfig.SECOND)); 360 | } 361 | 362 | public static final String FLING_CONFIG_DEFAULT = 363 | dl(FLING_DEF_BUTTONS) 364 | + dl(RIGHT_TAP_TAG) 365 | + dl(SystemAction.Home.mAction) + dl(SystemAction.Home.mLabelRes) + dl(EMPTY) // short tap 366 | + dl(SystemAction.GoogleNowOnTap.mAction) + dl(SystemAction.GoogleNowOnTap.mLabelRes) + dl(EMPTY) // long press 367 | + dl(SystemAction.LastApp.mAction) + dl(SystemAction.LastApp.mLabelRes) + dl(EMPTY) // double tap 368 | 369 | + dl(LEFT_TAP_TAG) 370 | + dl(SystemAction.Home.mAction) + dl(SystemAction.Home.mLabelRes) + dl(EMPTY) // short tap 371 | + dl(SystemAction.GoogleNowOnTap.mAction) + dl(SystemAction.GoogleNowOnTap.mLabelRes) + dl(EMPTY) // long press 372 | + dl(SystemAction.ScreenOff.mAction) + dl(SystemAction.ScreenOff.mLabelRes) + dl(EMPTY) // double tap 373 | 374 | + dl(RIGHT_FLING_TAG) 375 | + dl(SystemAction.Overview.mAction) + dl(SystemAction.Overview.mLabelRes) + dl(EMPTY) // short fling 376 | + dl(SystemAction.Assistant.mAction) + dl(SystemAction.Assistant.mLabelRes) + dl(EMPTY) // long fling 377 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // super fling? 378 | 379 | + dl(LEFT_FLING) 380 | + dl(SystemAction.Back.mAction) + dl(SystemAction.Back.mLabelRes) + dl(EMPTY) // short fling 381 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // long fling 382 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // super fling? 383 | 384 | + dl(UP_FLING) 385 | + dl(SystemAction.SplitScreen.mAction) + dl(SystemAction.SplitScreen.mLabelRes) + dl(EMPTY) // right side (short fling only) 386 | + dl(SystemAction.SplitScreen.mAction) + dl(SystemAction.SplitScreen.mLabelRes) + dl(EMPTY) // left side (short fling only) 387 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + EMPTY; 388 | 389 | @Override 390 | public int getConfigType() { 391 | return FLING; 392 | } 393 | 394 | @Override 395 | public String getUri() { 396 | return Settings.Secure.FLING_GESTURE_ACTIONS; 397 | } 398 | 399 | @Override 400 | public String getDefaultConfig() { 401 | return FLING_CONFIG_DEFAULT; 402 | } 403 | 404 | @Override 405 | public int getMaxButtons() { 406 | return FLING_MAX_BUTTONS; 407 | } 408 | 409 | @Override 410 | public Map getActionMap() { 411 | return configMap; 412 | } 413 | 414 | @Override 415 | public Bundle getConfigs(Context context) { 416 | return loadConfigsFromMap(context, defMap); 417 | } 418 | } 419 | 420 | public static class PiePrimary implements Defaults { 421 | public static final int PIE_PRIMARY_MAX_BUTTONS = 3; 422 | public static final String PIE_PRIMARY_DEF_BUTTONS = "3"; 423 | public static final String PIE_BACK_BUTTON_TAG = "pie_button_back"; 424 | public static final String PIE_HOME_BUTTON_TAG = "pie_button_home"; 425 | public static final String PIE_OVERVIEW_BUTTON_TAG = "pie_button_overview"; 426 | 427 | public static final String PIE_BACK_BUTTON_SINGLE_TAP_TAG = "pie_button_back_single_tap"; 428 | public static final String PIE_HOME_BUTTON_SINGLE_TAP_TAG = "pie_button_home_single_tap"; 429 | public static final String PIE_OVERVIEW_BUTTON_SINGLE_TAP_TAG = "pie_button_overview_single_tap"; 430 | 431 | public static final String PIE_BACK_BUTTON_LONG_PRESS_TAG = "pie_button_back_long_press"; 432 | public static final String PIE_HOME_BUTTON_LONG_PRESS_TAG = "pie_button_home_long_press"; 433 | public static final String PIE_OVERVIEW_BUTTON_LONG_PRESS_TAG = "pie_button_overview_long_press"; 434 | 435 | private static final Map configMap = new HashMap(); 436 | 437 | static { 438 | configMap.put(PIE_BACK_BUTTON_SINGLE_TAP_TAG, new ConfigMap(0, ActionConfig.PRIMARY)); 439 | configMap.put(PIE_HOME_BUTTON_SINGLE_TAP_TAG, new ConfigMap(1, ActionConfig.PRIMARY)); 440 | configMap.put(PIE_OVERVIEW_BUTTON_SINGLE_TAP_TAG, new ConfigMap(2, ActionConfig.PRIMARY)); 441 | configMap.put(PIE_BACK_BUTTON_LONG_PRESS_TAG, new ConfigMap(0, ActionConfig.SECOND)); 442 | configMap.put(PIE_HOME_BUTTON_LONG_PRESS_TAG, new ConfigMap(1, ActionConfig.SECOND)); 443 | configMap.put(PIE_OVERVIEW_BUTTON_LONG_PRESS_TAG, new ConfigMap(2, ActionConfig.SECOND)); 444 | } 445 | 446 | public static final String PIE_PRIMARY_CONFIG_DEFAULT = 447 | dl(PIE_PRIMARY_DEF_BUTTONS) 448 | + dl(PIE_BACK_BUTTON_TAG) 449 | + dl(SystemAction.Back.mAction) + dl(SystemAction.Back.mLabelRes) + dl(EMPTY) // single tap (PRIMARY) 450 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // long press (SECOND) 451 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // double tap (NO-OP on Pie) 452 | 453 | + dl(PIE_HOME_BUTTON_TAG) 454 | + dl(SystemAction.Home.mAction) + dl(SystemAction.Home.mLabelRes) + dl(EMPTY) 455 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 456 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 457 | 458 | + dl(PIE_OVERVIEW_BUTTON_TAG) 459 | + dl(SystemAction.Overview.mAction) + dl(SystemAction.Overview.mLabelRes) + dl(EMPTY) 460 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 461 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + EMPTY; // don't delimit final string 462 | 463 | 464 | @Override 465 | public int getConfigType() { 466 | return PIE_PRIMARY; 467 | } 468 | 469 | @Override 470 | public String getUri() { 471 | //return Settings.System.PIE_BUTTONS_CONFIG; 472 | return "pie_primary_config"; 473 | } 474 | 475 | @Override 476 | public String getDefaultConfig() { 477 | return PIE_PRIMARY_CONFIG_DEFAULT; 478 | } 479 | 480 | @Override 481 | public int getMaxButtons() { 482 | return PIE_PRIMARY_MAX_BUTTONS; 483 | } 484 | 485 | @Override 486 | public Map getActionMap() { 487 | return configMap; 488 | } 489 | 490 | @Override 491 | public Bundle getConfigs(Context context) { 492 | // TODO Auto-generated method stub 493 | return null; 494 | } 495 | } 496 | 497 | public static class PieSecond implements Defaults { 498 | public static final int PIE_SECOND_MAX_BUTTONS = 7; 499 | public static final String PIE_SECOND_DEF_BUTTONS = "5"; 500 | public static final String PIE_BUTTON1_TAG = "pie_button_1"; 501 | public static final String PIE_BUTTON2_TAG = "pie_button_2"; 502 | public static final String PIE_BUTTON3_TAG = "pie_button_3"; 503 | public static final String PIE_BUTTON4_TAG = "pie_button_4"; 504 | public static final String PIE_BUTTON5_TAG = "pie_button_5"; 505 | public static final String PIE_BUTTON6_TAG = "pie_button_6"; 506 | public static final String PIE_BUTTON7_TAG = "pie_button_7"; 507 | 508 | public static final String PIE_SECOND_BUTTON1_SINGLE_TAP_TAG = "pie_second_button_1_single_tap"; 509 | public static final String PIE_SECOND_BUTTON2_SINGLE_TAP_TAG = "pie_second_button_2_single_tap"; 510 | public static final String PIE_SECOND_BUTTON3_SINGLE_TAP_TAG = "pie_second_button_3_single_tap"; 511 | public static final String PIE_SECOND_BUTTON4_SINGLE_TAP_TAG = "pie_second_button_4_single_tap"; 512 | public static final String PIE_SECOND_BUTTON5_SINGLE_TAP_TAG = "pie_second_button_5_single_tap"; 513 | public static final String PIE_SECOND_BUTTON6_SINGLE_TAP_TAG = "pie_second_button_6_single_tap"; 514 | public static final String PIE_SECOND_BUTTON7_SINGLE_TAP_TAG = "pie_second_button_7_single_tap"; 515 | 516 | public static final String PIE_SECOND_BUTTON1_LONG_PRESS_TAG = "pie_second_button_1_long_press"; 517 | public static final String PIE_SECOND_BUTTON2_LONG_PRESS_TAG = "pie_second_button_2_long_press"; 518 | public static final String PIE_SECOND_BUTTON3_LONG_PRESS_TAG = "pie_second_button_3_long_press"; 519 | public static final String PIE_SECOND_BUTTON4_LONG_PRESS_TAG = "pie_second_button_4_long_press"; 520 | public static final String PIE_SECOND_BUTTON5_LONG_PRESS_TAG = "pie_second_button_5_long_press"; 521 | public static final String PIE_SECOND_BUTTON6_LONG_PRESS_TAG = "pie_second_button_6_long_press"; 522 | public static final String PIE_SECOND_BUTTON7_LONG_PRESS_TAG = "pie_second_button_7_long_press"; 523 | 524 | private static final Map configMap = new HashMap(); 525 | 526 | static { 527 | configMap.put(PIE_SECOND_BUTTON1_SINGLE_TAP_TAG, new ConfigMap(0, ActionConfig.PRIMARY)); 528 | configMap.put(PIE_SECOND_BUTTON2_SINGLE_TAP_TAG, new ConfigMap(1, ActionConfig.PRIMARY)); 529 | configMap.put(PIE_SECOND_BUTTON3_SINGLE_TAP_TAG, new ConfigMap(2, ActionConfig.PRIMARY)); 530 | configMap.put(PIE_SECOND_BUTTON4_SINGLE_TAP_TAG, new ConfigMap(3, ActionConfig.PRIMARY)); 531 | configMap.put(PIE_SECOND_BUTTON5_SINGLE_TAP_TAG, new ConfigMap(4, ActionConfig.PRIMARY)); 532 | configMap.put(PIE_SECOND_BUTTON6_SINGLE_TAP_TAG, new ConfigMap(5, ActionConfig.PRIMARY)); 533 | configMap.put(PIE_SECOND_BUTTON7_SINGLE_TAP_TAG, new ConfigMap(6, ActionConfig.PRIMARY)); 534 | configMap.put(PIE_SECOND_BUTTON1_LONG_PRESS_TAG, new ConfigMap(0, ActionConfig.SECOND)); 535 | configMap.put(PIE_SECOND_BUTTON2_LONG_PRESS_TAG, new ConfigMap(1, ActionConfig.SECOND)); 536 | configMap.put(PIE_SECOND_BUTTON3_LONG_PRESS_TAG, new ConfigMap(2, ActionConfig.SECOND)); 537 | configMap.put(PIE_SECOND_BUTTON4_LONG_PRESS_TAG, new ConfigMap(3, ActionConfig.SECOND)); 538 | configMap.put(PIE_SECOND_BUTTON5_LONG_PRESS_TAG, new ConfigMap(4, ActionConfig.SECOND)); 539 | configMap.put(PIE_SECOND_BUTTON6_LONG_PRESS_TAG, new ConfigMap(5, ActionConfig.SECOND)); 540 | configMap.put(PIE_SECOND_BUTTON7_LONG_PRESS_TAG, new ConfigMap(6, ActionConfig.SECOND)); 541 | } 542 | 543 | public static final String PIE_SECOND_CONFIG_DEFAULT = 544 | dl(PIE_SECOND_DEF_BUTTONS) 545 | + dl(PIE_BUTTON1_TAG) 546 | + dl(SystemAction.PowerMenu.mAction) + dl(SystemAction.PowerMenu.mLabelRes) + dl(EMPTY) // single tap (PRIMARY) 547 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // long press (SECOND) 548 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) // double tap (NO-OP on Pie) 549 | 550 | + dl(PIE_BUTTON2_TAG) 551 | + dl(SystemAction.NotificationPanel.mAction) + dl(SystemAction.NotificationPanel.mLabelRes) + dl(EMPTY) 552 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 553 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 554 | 555 | + dl(PIE_BUTTON3_TAG) 556 | + dl(SystemAction.Assistant.mAction) + dl(SystemAction.Assistant.mLabelRes) + dl(EMPTY) 557 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 558 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 559 | 560 | + dl(PIE_BUTTON4_TAG) 561 | + dl(SystemAction.Screenshot.mAction) + dl(SystemAction.Screenshot.mLabelRes) + dl(EMPTY) 562 | + dl(SystemAction.RegionScreenshot.mAction) + dl(SystemAction.RegionScreenshot.mLabelRes) + dl(EMPTY) 563 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 564 | 565 | + dl(PIE_BUTTON5_TAG) 566 | + dl(SystemAction.LastApp.mAction) + dl(SystemAction.LastApp.mLabelRes) + dl(EMPTY) 567 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + dl(EMPTY) 568 | + dl(SystemAction.NoAction.mAction) + dl(SystemAction.NoAction.mLabelRes) + EMPTY; 569 | 570 | @Override 571 | public int getConfigType() { 572 | return PIE_SECONDARY; 573 | } 574 | 575 | @Override 576 | public String getUri() { 577 | //return Settings.System.PIE_BUTTONS_CONFIG_SECOND_LAYER; 578 | return "pie_second_config"; 579 | } 580 | 581 | @Override 582 | public String getDefaultConfig() { 583 | return PIE_SECOND_CONFIG_DEFAULT; 584 | } 585 | 586 | @Override 587 | public int getMaxButtons() { 588 | return PIE_SECOND_MAX_BUTTONS; 589 | } 590 | 591 | @Override 592 | public Map getActionMap() { 593 | return configMap; 594 | } 595 | 596 | @Override 597 | public Bundle getConfigs(Context context) { 598 | // TODO Auto-generated method stub 599 | return null; 600 | } 601 | 602 | } 603 | 604 | private static Bundle loadConfigsFromMap(Context ctx, Map configMap) { 605 | Bundle b = new Bundle(); 606 | for (Map.Entry entry : configMap.entrySet()) { 607 | ConfigHolder holder = entry.getValue(); 608 | Object obj = DUActionUtils.getValue(ctx, holder.name, holder.type, holder.format, 609 | holder.pkg); 610 | DUActionUtils.putValue(holder.name, obj, holder.type, b); 611 | } 612 | return b; 613 | } 614 | 615 | private static class ConfigHolder { 616 | public String pkg; 617 | public String name; 618 | public String format; 619 | public String type; 620 | 621 | public ConfigHolder(String pkg, String name, String type) { 622 | this(pkg, name, null, type); 623 | } 624 | 625 | public ConfigHolder(String pkg, String name, String format, String type) { 626 | this.pkg = pkg; 627 | this.name = name; 628 | this.format = format; 629 | this.type = type; 630 | } 631 | } 632 | 633 | public static class ConfigMap { 634 | public int button = -1; 635 | public int action = -1; 636 | 637 | public ConfigMap() { 638 | }; 639 | 640 | public ConfigMap(int button, int action) { 641 | this.button = button; 642 | this.action = action; 643 | } 644 | } 645 | 646 | public static final int PIE_PRIMARY_MAX_BUTTONS = 5; 647 | public static final int PIE_SECONDAY_MAX_BUTTONS = 7; 648 | 649 | } 650 | -------------------------------------------------------------------------------- /src/com/android/internal/utils/du/ActionHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 The TeamEos Project 3 | * Copyright (C) 2016-2017 The DirtyUnicorns Project 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | * 17 | * Launches actions assigned to widgets. Creates bundles of state based 18 | * on the type of action passed. 19 | * 20 | */ 21 | 22 | package com.android.internal.utils.du; 23 | 24 | import android.app.ActivityManager; 25 | import android.app.ActivityManagerNative; 26 | import android.app.ActivityOptions; 27 | import android.app.IActivityManager; 28 | import android.app.SearchManager; 29 | import android.app.ActivityManager.RunningAppProcessInfo; 30 | import android.app.usage.UsageStats; 31 | import android.app.usage.UsageStatsManager; 32 | import android.bluetooth.BluetoothAdapter; 33 | import android.content.ActivityNotFoundException; 34 | import android.content.ContentResolver; 35 | import android.content.Context; 36 | import android.content.ComponentName; 37 | import android.content.Intent; 38 | import android.content.pm.ApplicationInfo; 39 | import android.content.pm.PackageManager; 40 | import android.content.pm.ResolveInfo; 41 | import android.content.res.Resources; 42 | import android.graphics.drawable.Drawable; 43 | import android.hardware.input.InputManager; 44 | import android.media.AudioManager; 45 | import android.media.ToneGenerator; 46 | import android.media.session.MediaSessionLegacyHelper; 47 | import android.net.ConnectivityManager; 48 | import android.net.wifi.WifiManager; 49 | import android.os.Bundle; 50 | import android.os.Handler; 51 | import android.os.Looper; 52 | import android.os.PowerManager; 53 | import android.os.Process; 54 | import android.os.RemoteException; 55 | import android.os.ServiceManager; 56 | import android.os.SystemClock; 57 | import android.os.UserHandle; 58 | import android.os.Vibrator; 59 | import android.provider.Settings; 60 | import android.service.wallpaper.WallpaperService; 61 | import android.text.TextUtils; 62 | import android.util.Log; 63 | import android.util.Slog; 64 | import android.view.IWindowManager; 65 | import android.view.InputDevice; 66 | import android.view.KeyCharacterMap; 67 | import android.view.KeyEvent; 68 | import android.view.WindowManagerGlobal; 69 | import android.view.WindowManagerPolicyControl; 70 | import android.view.inputmethod.InputMethodManager; 71 | import android.widget.Toast; 72 | 73 | import java.util.ArrayList; 74 | import java.util.Collections; 75 | import java.util.Comparator; 76 | import java.util.HashMap; 77 | import java.util.HashSet; 78 | import java.util.List; 79 | import java.util.Map; 80 | import java.util.Set; 81 | 82 | import com.android.internal.statusbar.IStatusBarService; 83 | import com.android.internal.utils.du.Config.ActionConfig; 84 | 85 | public class ActionHandler { 86 | public static String TAG = ActionHandler.class.getSimpleName(); 87 | 88 | public static final String SYSTEM_PREFIX = "task"; 89 | public static final String SYSTEMUI = "com.android.systemui"; 90 | 91 | // track and filter special actions 92 | public static final String TASK_IME = "task_ime"; 93 | public static final String TASK_MEDIA = "task_media"; 94 | public static final String TASK_SOUNDMODE = "task_soundmode"; 95 | 96 | public static final String SYSTEMUI_TASK_NO_ACTION = "task_no_action"; 97 | public static final String SYSTEMUI_TASK_SETTINGS_PANEL = "task_settings_panel"; 98 | public static final String SYSTEMUI_TASK_NOTIFICATION_PANEL = "task_notification_panel"; 99 | public static final String SYSTEMUI_TASK_SCREENSHOT = "task_screenshot"; 100 | public static final String SYSTEMUI_TASK_REGION_SCREENSHOT = "task_region_screenshot"; 101 | public static final String SYSTEMUI_TASK_SCREENRECORD = "task_screenrecord"; 102 | // public static final String SYSTEMUI_TASK_AUDIORECORD = 103 | // "task_audiorecord"; 104 | public static final String SYSTEMUI_TASK_EXPANDED_DESKTOP = "task_expanded_desktop"; 105 | public static final String SYSTEMUI_TASK_SCREENOFF = "task_screenoff"; 106 | public static final String SYSTEMUI_TASK_KILL_PROCESS = "task_killcurrent"; 107 | public static final String SYSTEMUI_TASK_ASSIST = "task_assist"; 108 | public static final String SYSTEMUI_TASK_GOOGLE_NOW_ON_TAP = "task_google_now_on_tap"; 109 | public static final String SYSTEMUI_TASK_POWER_MENU = "task_powermenu"; 110 | public static final String SYSTEMUI_TASK_TORCH = "task_torch"; 111 | public static final String SYSTEMUI_TASK_CAMERA = "task_camera"; 112 | public static final String SYSTEMUI_TASK_BT = "task_bt"; 113 | public static final String SYSTEMUI_TASK_WIFI = "task_wifi"; 114 | public static final String SYSTEMUI_TASK_WIFIAP = "task_wifiap"; 115 | public static final String SYSTEMUI_TASK_RECENTS = "task_recents"; 116 | public static final String SYSTEMUI_TASK_LAST_APP = "task_last_app"; 117 | public static final String SYSTEMUI_TASK_VOICE_SEARCH = "task_voice_search"; 118 | public static final String SYSTEMUI_TASK_APP_SEARCH = "task_app_search"; 119 | public static final String SYSTEMUI_TASK_MENU = "task_menu"; 120 | public static final String SYSTEMUI_TASK_BACK = "task_back"; 121 | public static final String SYSTEMUI_TASK_HOME = "task_home"; 122 | public static final String SYSTEMUI_TASK_IME_SWITCHER = "task_ime_switcher"; 123 | public static final String SYSTEMUI_TASK_IME_NAVIGATION_LEFT = "task_ime_navigation_left"; 124 | public static final String SYSTEMUI_TASK_IME_NAVIGATION_RIGHT = "task_ime_navigation_right"; 125 | public static final String SYSTEMUI_TASK_IME_NAVIGATION_UP = "task_ime_navigation_up"; 126 | public static final String SYSTEMUI_TASK_IME_NAVIGATION_DOWN = "task_ime_navigation_down"; 127 | public static final String SYSTEMUI_TASK_MEDIA_PREVIOUS = "task_media_previous"; 128 | public static final String SYSTEMUI_TASK_MEDIA_NEXT = "task_media_next"; 129 | public static final String SYSTEMUI_TASK_MEDIA_PLAY_PAUSE = "task_media_play_pause"; 130 | public static final String SYSTEMUI_TASK_SOUNDMODE_VIB = "task_soundmode_vib"; 131 | public static final String SYSTEMUI_TASK_SOUNDMODE_SILENT = "task_soundmode_silent"; 132 | public static final String SYSTEMUI_TASK_SOUNDMODE_VIB_SILENT = "task_soundmode_vib_silent"; 133 | public static final String SYSTEMUI_TASK_WAKE_DEVICE = "task_wake_device"; 134 | public static final String SYSTEMUI_TASK_STOP_SCREENPINNING = "task_stop_screenpinning"; 135 | public static final String SYSTEMUI_TASK_CLEAR_NOTIFICATIONS = "task_clear_notifications"; 136 | public static final String SYSTEMUI_TASK_VOLUME_PANEL = "task_volume_panel"; 137 | public static final String SYSTEMUI_TASK_EDITING_SMARTBAR = "task_editing_smartbar"; 138 | public static final String SYSTEMUI_TASK_SPLIT_SCREEN = "task_split_screen"; 139 | public static final String SYSTEMUI_TASK_ONE_HANDED_MODE_LEFT = "task_one_handed_mode_left"; 140 | public static final String SYSTEMUI_TASK_ONE_HANDED_MODE_RIGHT = "task_one_handed_mode_right"; 141 | public static final String SYSTEMUI_TASK_ASSISTANT_SOUND_SEARCH = "task_assistant_sound_search"; 142 | 143 | public static final String INTENT_SHOW_POWER_MENU = "action_handler_show_power_menu"; 144 | public static final String INTENT_TOGGLE_SCREENRECORD = "action_handler_toggle_screenrecord"; 145 | public static final String INTENT_SCREENSHOT = "action_handler_screenshot"; 146 | public static final String INTENT_REGION_SCREENSHOT = "action_handler_region_screenshot"; 147 | 148 | // remove actions from here as they come back on deck 149 | static final Set sDisabledActions = new HashSet(); 150 | static { 151 | sDisabledActions.add(SYSTEMUI_TASK_SCREENRECORD); 152 | sDisabledActions.add(SYSTEMUI_TASK_ONE_HANDED_MODE_LEFT); 153 | sDisabledActions.add(SYSTEMUI_TASK_ONE_HANDED_MODE_RIGHT); 154 | // we need to make this more reliable when the user tap the partial screenshot button 155 | // quickly and more times 156 | sDisabledActions.add(SYSTEMUI_TASK_REGION_SCREENSHOT); 157 | } 158 | 159 | static enum SystemAction { 160 | NoAction(SYSTEMUI_TASK_NO_ACTION, SYSTEMUI, "label_action_no_action", "ic_sysbar_no_action"), 161 | SettingsPanel(SYSTEMUI_TASK_SETTINGS_PANEL, SYSTEMUI, "label_action_settings_panel", "ic_sysbar_settings_panel"), 162 | NotificationPanel(SYSTEMUI_TASK_NOTIFICATION_PANEL, SYSTEMUI, "label_action_notification_panel", "ic_sysbar_notification_panel"), 163 | Screenshot(SYSTEMUI_TASK_SCREENSHOT, SYSTEMUI, "label_action_screenshot", "ic_sysbar_screenshot"), 164 | RegionScreenshot(SYSTEMUI_TASK_REGION_SCREENSHOT, SYSTEMUI, "label_action_region_screenshot", "ic_sysbar_region_screenshot"), 165 | Screenrecord(SYSTEMUI_TASK_SCREENRECORD, SYSTEMUI, "label_action_screenrecord", "ic_sysbar_record_screen"), 166 | ExpandedDesktop(SYSTEMUI_TASK_EXPANDED_DESKTOP, SYSTEMUI, "label_action_expanded_desktop", "ic_sysbar_expanded_desktop"), 167 | ScreenOff(SYSTEMUI_TASK_SCREENOFF, SYSTEMUI, "label_action_screen_off", "ic_sysbar_screen_off"), 168 | KillApp(SYSTEMUI_TASK_KILL_PROCESS, SYSTEMUI, "label_action_force_close_app", "ic_sysbar_killtask"), 169 | Assistant(SYSTEMUI_TASK_ASSIST, SYSTEMUI, "label_action_search_assistant", "ic_sysbar_assist"), 170 | GoogleNowOnTap(SYSTEMUI_TASK_GOOGLE_NOW_ON_TAP, SYSTEMUI, "label_action_google_now_on_tap", "ic_sysbar_google_now_on_tap"), 171 | VoiceSearch(SYSTEMUI_TASK_VOICE_SEARCH, SYSTEMUI, "label_action_voice_search", "ic_sysbar_search"), 172 | InAppSearch(SYSTEMUI_TASK_APP_SEARCH, SYSTEMUI, "label_action_in_app_search", "ic_sysbar_in_app_search"), 173 | Flashlight(SYSTEMUI_TASK_TORCH, SYSTEMUI, "label_action_flashlight", "ic_sysbar_torch"), 174 | Bluetooth(SYSTEMUI_TASK_BT, SYSTEMUI, "label_action_bluetooth", "ic_sysbar_bt"), 175 | WiFi(SYSTEMUI_TASK_WIFI, SYSTEMUI, "label_action_wifi", "ic_sysbar_wifi"), 176 | Hotspot(SYSTEMUI_TASK_WIFIAP, SYSTEMUI, "label_action_hotspot", "ic_sysbar_hotspot"), 177 | LastApp(SYSTEMUI_TASK_LAST_APP, SYSTEMUI, "label_action_last_app", "ic_sysbar_lastapp"), 178 | Overview(SYSTEMUI_TASK_RECENTS, SYSTEMUI, "label_action_overview", "ic_sysbar_recent"), 179 | PowerMenu(SYSTEMUI_TASK_POWER_MENU, SYSTEMUI, "label_action_power_menu", "ic_sysbar_power_menu"), 180 | Menu(SYSTEMUI_TASK_MENU, SYSTEMUI, "label_action_menu", "ic_sysbar_menu"), 181 | Back(SYSTEMUI_TASK_BACK, SYSTEMUI, "label_action_back", "ic_sysbar_back"), 182 | Home(SYSTEMUI_TASK_HOME, SYSTEMUI, "label_action_home", "ic_sysbar_home"), 183 | Ime(SYSTEMUI_TASK_IME_SWITCHER, SYSTEMUI, "label_action_ime_switcher", "ic_ime_switcher_smartbar"), 184 | StopScreenPinning(SYSTEMUI_TASK_STOP_SCREENPINNING, SYSTEMUI, "label_action_stop_screenpinning", "ic_smartbar_screen_pinning_off"), 185 | ImeArrowDown(SYSTEMUI_TASK_IME_NAVIGATION_DOWN, SYSTEMUI, "label_action_ime_down", "ic_sysbar_ime_down"), 186 | ImeArrowLeft(SYSTEMUI_TASK_IME_NAVIGATION_LEFT, SYSTEMUI, "label_action_ime_left", "ic_sysbar_ime_left"), 187 | ImeArrowRight(SYSTEMUI_TASK_IME_NAVIGATION_RIGHT, SYSTEMUI, "label_action_ime_right", "ic_sysbar_ime_right"), 188 | ImeArrowUp(SYSTEMUI_TASK_IME_NAVIGATION_UP, SYSTEMUI, "label_action_ime_up", "ic_sysbar_ime_up"), 189 | ClearNotifications(SYSTEMUI_TASK_CLEAR_NOTIFICATIONS, SYSTEMUI, "label_action_clear_notifications", "ic_sysbar_clear_notifications"), 190 | VolumePanel(SYSTEMUI_TASK_VOLUME_PANEL, SYSTEMUI, "label_action_volume_panel", "ic_sysbar_volume_panel"), 191 | EditingSmartbar(SYSTEMUI_TASK_EDITING_SMARTBAR, SYSTEMUI, "label_action_editing_smartbar", "ic_sysbar_editing_smartbar"), 192 | SplitScreen(SYSTEMUI_TASK_SPLIT_SCREEN, SYSTEMUI, "label_action_split_screen", "ic_sysbar_docked"), 193 | OneHandedModeLeft(SYSTEMUI_TASK_ONE_HANDED_MODE_LEFT, SYSTEMUI, "label_action_one_handed_mode_left", "ic_sysbar_one_handed_mode_left"), 194 | OneHandedModeRight(SYSTEMUI_TASK_ONE_HANDED_MODE_RIGHT, SYSTEMUI, "label_action_one_handed_mode_right", "ic_sysbar_one_handed_mode_right"), 195 | MediaArrowLeft(SYSTEMUI_TASK_MEDIA_PREVIOUS, SYSTEMUI, "label_action_media_left", "ic_skip_previous"), 196 | MediaArrowRight(SYSTEMUI_TASK_MEDIA_NEXT, SYSTEMUI, "label_action_media_right", "ic_skip_next"), 197 | AssistantSoundSearch(SYSTEMUI_TASK_ASSISTANT_SOUND_SEARCH, SYSTEMUI, "label_action_assistant_sound_search", "ic_assistant_sound_search"); 198 | 199 | String mAction; 200 | String mResPackage; 201 | String mLabelRes; 202 | String mIconRes; 203 | String mDarkIconRes; 204 | 205 | private SystemAction(String action, String resPackage, String labelRes, String iconRes) { 206 | mAction = action; 207 | mResPackage = resPackage; 208 | mLabelRes = labelRes; 209 | mIconRes = iconRes; 210 | mDarkIconRes = iconRes + "_dark"; 211 | } 212 | 213 | private ActionConfig create(Context ctx) { 214 | return new ActionConfig(ctx, mAction); 215 | } 216 | } 217 | 218 | /* 219 | * Enumerated system actions with label and drawable support 220 | */ 221 | static SystemAction[] systemActions = new SystemAction[] { 222 | SystemAction.NoAction, SystemAction.SettingsPanel, 223 | SystemAction.NotificationPanel, SystemAction.Screenshot, 224 | SystemAction.ScreenOff, SystemAction.KillApp, 225 | SystemAction.Assistant, SystemAction.GoogleNowOnTap, 226 | SystemAction.Flashlight, SystemAction.Bluetooth, 227 | SystemAction.WiFi, SystemAction.Hotspot, 228 | SystemAction.LastApp, SystemAction.PowerMenu, 229 | SystemAction.Overview,SystemAction.Menu, 230 | SystemAction.Back, SystemAction.VoiceSearch, 231 | SystemAction.Home, SystemAction.ExpandedDesktop, 232 | SystemAction.Screenrecord, SystemAction.Ime, 233 | SystemAction.StopScreenPinning, SystemAction.ImeArrowDown, 234 | SystemAction.ImeArrowLeft, SystemAction.ImeArrowRight, 235 | SystemAction.ImeArrowUp, SystemAction.InAppSearch, 236 | SystemAction.VolumePanel, SystemAction.ClearNotifications, 237 | SystemAction.EditingSmartbar, SystemAction.SplitScreen, 238 | SystemAction.RegionScreenshot, SystemAction.OneHandedModeLeft, 239 | SystemAction.OneHandedModeRight, SystemAction.MediaArrowLeft, 240 | SystemAction.MediaArrowRight, SystemAction.AssistantSoundSearch 241 | }; 242 | 243 | public static class ActionIconResources { 244 | Drawable[] mDrawables; 245 | Drawable[] mDarkDrawables; 246 | Map mIndexMap; 247 | 248 | public ActionIconResources(Resources res) { 249 | mDrawables = new Drawable[systemActions.length]; 250 | mDarkDrawables = new Drawable[systemActions.length]; 251 | mIndexMap = new HashMap(); 252 | for (int i = 0; i < systemActions.length; i++) { 253 | mIndexMap.put(systemActions[i].mAction, i); 254 | mDrawables[i] = DUActionUtils.getDrawable(res, systemActions[i].mIconRes, 255 | systemActions[i].mResPackage); 256 | mDarkDrawables[i] = DUActionUtils.getDrawable(res, systemActions[i].mDarkIconRes, 257 | systemActions[i].mResPackage); 258 | } 259 | } 260 | 261 | public void updateResources(Resources res) { 262 | for (int i = 0; i < mDrawables.length; i++) { 263 | mDrawables[i] = DUActionUtils.getDrawable(res, systemActions[i].mIconRes, 264 | systemActions[i].mResPackage); 265 | mDarkDrawables[i] = DUActionUtils.getDrawable(res, systemActions[i].mDarkIconRes, 266 | systemActions[i].mResPackage); 267 | } 268 | } 269 | 270 | public Drawable getActionDrawable(String action) { 271 | return mDrawables[mIndexMap.get(action)]; 272 | } 273 | 274 | public Drawable getDarkActionDrawable(String action) { 275 | return mDarkDrawables[mIndexMap.get(action)]; 276 | } 277 | } 278 | 279 | /* 280 | * Default list to display in an action picker 281 | * Filter by device capabilities and actions used internally 282 | * but we don't really want as assignable 283 | */ 284 | public static ArrayList getSystemActions(Context context) { 285 | ArrayList bundle = new ArrayList(); 286 | for (int i = 0; i < systemActions.length; i++) { 287 | ActionConfig c = systemActions[i].create(context); 288 | String action = c.getAction(); 289 | if (sDisabledActions.contains(action)) { 290 | continue; 291 | } 292 | if (TextUtils.equals(action, SYSTEMUI_TASK_STOP_SCREENPINNING) 293 | || TextUtils.equals(action, SYSTEMUI_TASK_IME_NAVIGATION_DOWN) 294 | || TextUtils.equals(action, SYSTEMUI_TASK_IME_NAVIGATION_LEFT) 295 | || TextUtils.equals(action, SYSTEMUI_TASK_IME_NAVIGATION_RIGHT) 296 | || TextUtils.equals(action, SYSTEMUI_TASK_IME_NAVIGATION_UP) 297 | || TextUtils.equals(action, SYSTEMUI_TASK_IME_SWITCHER) 298 | || TextUtils.equals(action, SYSTEMUI_TASK_MEDIA_PREVIOUS) 299 | || TextUtils.equals(action, SYSTEMUI_TASK_MEDIA_NEXT)) { 300 | continue; 301 | } else if (TextUtils.equals(action, SYSTEMUI_TASK_WIFIAP) 302 | && !DUActionUtils.deviceSupportsMobileData(context)) { 303 | continue; 304 | } else if (TextUtils.equals(action, SYSTEMUI_TASK_BT) 305 | && !DUActionUtils.deviceSupportsBluetooth()) { 306 | continue; 307 | } else if (TextUtils.equals(action, SYSTEMUI_TASK_TORCH) 308 | && !DUActionUtils.deviceSupportsFlashLight(context)) { 309 | continue; 310 | } else if (TextUtils.equals(action, SYSTEMUI_TASK_CAMERA) 311 | && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) { 312 | continue; 313 | } else if (TextUtils.equals(action, SYSTEMUI_TASK_SCREENRECORD)) { 314 | if (!DUActionUtils.getBoolean(context, "config_enableScreenrecordChord", 315 | DUActionUtils.PACKAGE_ANDROID)) { 316 | continue; 317 | } 318 | } else if (TextUtils.equals(action, SYSTEMUI_TASK_EDITING_SMARTBAR)) { 319 | // don't allow smartbar editor on Fling 320 | if (Settings.Secure.getIntForUser(context.getContentResolver(), 321 | Settings.Secure.NAVIGATION_BAR_MODE, 0, 322 | UserHandle.USER_CURRENT) == 1) { 323 | continue; 324 | } 325 | } 326 | bundle.add(c); 327 | } 328 | Collections.sort(bundle); 329 | return bundle; 330 | } 331 | 332 | private static final class StatusBarHelper { 333 | private static boolean isPreloaded = false; 334 | private static IStatusBarService mService = null; 335 | 336 | private static IStatusBarService getStatusBarService() { 337 | synchronized (StatusBarHelper.class) { 338 | if (mService == null) { 339 | try { 340 | mService = IStatusBarService.Stub.asInterface( 341 | ServiceManager.getService("statusbar")); 342 | } catch (Exception e) { 343 | } 344 | } 345 | return mService; 346 | } 347 | } 348 | 349 | private static void dispatchNavigationEditorResult(Intent intent) { 350 | IStatusBarService service = getStatusBarService(); 351 | if (service != null) { 352 | try { 353 | service.dispatchNavigationEditorResults(intent); 354 | } catch (RemoteException e) { 355 | e.printStackTrace(); 356 | } 357 | } 358 | } 359 | 360 | private static void toggleNavigationEditor() { 361 | IStatusBarService service = getStatusBarService(); 362 | try { 363 | service.toggleNavigationEditor(); 364 | } catch (RemoteException e) { 365 | e.printStackTrace(); 366 | } 367 | } 368 | 369 | private static void toggleFlashlight() { 370 | IStatusBarService service = getStatusBarService(); 371 | try { 372 | service.toggleFlashlight(); 373 | } catch (RemoteException e) { 374 | e.printStackTrace(); 375 | } 376 | } 377 | 378 | private static void toggleRecentsApps() { 379 | IStatusBarService service = getStatusBarService(); 380 | if (service != null) { 381 | try { 382 | sendCloseSystemWindows("recentapps"); 383 | service.toggleRecentApps(); 384 | } catch (RemoteException e) { 385 | return; 386 | } 387 | isPreloaded = false; 388 | } 389 | } 390 | 391 | private static void cancelPreloadRecentApps() { 392 | if (isPreloaded == false) 393 | return; 394 | IStatusBarService service = getStatusBarService(); 395 | if (service != null) { 396 | try { 397 | service.cancelPreloadRecentApps(); 398 | } catch (Exception e) { 399 | return; 400 | } 401 | } 402 | isPreloaded = false; 403 | } 404 | 405 | private static void preloadRecentApps() { 406 | IStatusBarService service = getStatusBarService(); 407 | if (service != null) { 408 | try { 409 | service.preloadRecentApps(); 410 | } catch (RemoteException e) { 411 | isPreloaded = false; 412 | return; 413 | } 414 | isPreloaded = true; 415 | } 416 | } 417 | 418 | private static void expandNotificationPanel() { 419 | IStatusBarService service = getStatusBarService(); 420 | if (service != null) { 421 | try { 422 | service.expandNotificationsPanel(); 423 | } catch (RemoteException e) { 424 | } 425 | } 426 | } 427 | 428 | private static void expandSettingsPanel() { 429 | IStatusBarService service = getStatusBarService(); 430 | if (service != null) { 431 | try { 432 | service.expandSettingsPanel(null); 433 | } catch (RemoteException e) { 434 | } 435 | } 436 | } 437 | 438 | private static void fireGoogleNowOnTap() { 439 | IStatusBarService service = getStatusBarService(); 440 | if (service != null) { 441 | try { 442 | service.startAssist(new Bundle()); 443 | } catch (RemoteException e) { 444 | } 445 | } 446 | } 447 | 448 | private static void splitScreen() { 449 | IStatusBarService service = getStatusBarService(); 450 | if (service != null) { 451 | try { 452 | service.toggleSplitScreen(); 453 | } catch (RemoteException e) { 454 | } 455 | } 456 | } 457 | /* 458 | private static void fireIntentAfterKeyguard(Intent intent) { 459 | IStatusBarService service = getStatusBarService(); 460 | if (service != null) { 461 | try { 462 | service.showCustomIntentAfterKeyguard(intent); 463 | } catch (RemoteException e) { 464 | } 465 | } 466 | } 467 | */ 468 | private static void clearAllNotifications() { 469 | IStatusBarService service = getStatusBarService(); 470 | if (service != null) { 471 | try { 472 | service.onClearAllNotifications(ActivityManager.getCurrentUser()); 473 | } catch (RemoteException e) { 474 | } 475 | } 476 | } 477 | } 478 | 479 | public static void toggleRecentApps() { 480 | StatusBarHelper.toggleRecentsApps(); 481 | } 482 | 483 | public static void cancelPreloadRecentApps() { 484 | StatusBarHelper.cancelPreloadRecentApps(); 485 | } 486 | 487 | public static void preloadRecentApps() { 488 | StatusBarHelper.preloadRecentApps(); 489 | } 490 | /* 491 | public static void performTaskFromKeyguard(Context ctx, String action) { 492 | // null: throw it out 493 | if (action == null) { 494 | return; 495 | } 496 | // not a system action, should be intent 497 | if (!action.startsWith(SYSTEM_PREFIX)) { 498 | Intent intent = DUActionUtils.getIntent(action); 499 | if (intent == null) { 500 | return; 501 | } 502 | StatusBarHelper.fireIntentAfterKeyguard(intent); 503 | } else { 504 | performTask(ctx, action); 505 | } 506 | } 507 | */ 508 | public static void dispatchNavigationEditorResult(Intent intent) { 509 | StatusBarHelper.dispatchNavigationEditorResult(intent); 510 | } 511 | 512 | public static void performTask(Context context, String action) { 513 | // null: throw it out 514 | if (action == null) { 515 | return; 516 | } 517 | if (sDisabledActions.contains(action)) { 518 | return; 519 | } 520 | // not a system action, should be intent 521 | if (!action.startsWith(SYSTEM_PREFIX)) { 522 | Intent intent = DUActionUtils.getIntent(action); 523 | if (intent == null) { 524 | return; 525 | } 526 | launchActivity(context, intent); 527 | return; 528 | } else if (action.equals(SYSTEMUI_TASK_NO_ACTION)) { 529 | return; 530 | } else if (action.equals(SYSTEMUI_TASK_KILL_PROCESS)) { 531 | killProcess(context); 532 | return; 533 | } else if (action.equals(SYSTEMUI_TASK_SCREENSHOT)) { 534 | sendCommandToWindowManager(new Intent(INTENT_SCREENSHOT)); 535 | return; 536 | } else if (action.equals(SYSTEMUI_TASK_REGION_SCREENSHOT)) { 537 | sendCommandToWindowManager(new Intent(INTENT_REGION_SCREENSHOT)); 538 | return; 539 | } else if (action.equals(SYSTEMUI_TASK_SCREENRECORD)) { 540 | sendCommandToWindowManager(new Intent(INTENT_TOGGLE_SCREENRECORD)); 541 | return; 542 | // } else if (action.equals(SYSTEMUI_TASK_AUDIORECORD)) { 543 | // takeAudiorecord(); 544 | } else if (action.equals(SYSTEMUI_TASK_EXPANDED_DESKTOP)) { 545 | toggleExpandedDesktop(context); 546 | return; 547 | } else if (action.equals(SYSTEMUI_TASK_SCREENOFF)) { 548 | screenOff(context); 549 | return; 550 | } else if (action.equals(SYSTEMUI_TASK_WAKE_DEVICE)) { 551 | PowerManager powerManager = 552 | (PowerManager) context.getSystemService(Context.POWER_SERVICE); 553 | if (!powerManager.isScreenOn()) { 554 | powerManager.wakeUp(SystemClock.uptimeMillis()); 555 | } 556 | return; 557 | } else if (action.equals(SYSTEMUI_TASK_ASSIST)) { 558 | launchAssistAction(context); 559 | return; 560 | } else if (action.equals(SYSTEMUI_TASK_GOOGLE_NOW_ON_TAP)) { 561 | StatusBarHelper.fireGoogleNowOnTap(); 562 | return; 563 | } else if (action.equals(SYSTEMUI_TASK_POWER_MENU)) { 564 | sendCommandToWindowManager(new Intent(INTENT_SHOW_POWER_MENU)); 565 | return; 566 | } else if (action.equals(SYSTEMUI_TASK_TORCH)) { 567 | StatusBarHelper.toggleFlashlight(); 568 | return; 569 | } else if (action.equals(SYSTEMUI_TASK_CAMERA)) { 570 | launchCamera(context); 571 | return; 572 | } else if (action.equals(SYSTEMUI_TASK_WIFI)) { 573 | toggleWifi(context); 574 | return; 575 | } else if (action.equals(SYSTEMUI_TASK_WIFIAP)) { 576 | toggleWifiAP(context); 577 | return; 578 | } else if (action.equals(SYSTEMUI_TASK_BT)) { 579 | toggleBluetooth(); 580 | return; 581 | } else if (action.equals(SYSTEMUI_TASK_RECENTS)) { 582 | toggleRecentApps(); 583 | return; 584 | } else if (action.equals(SYSTEMUI_TASK_LAST_APP)) { 585 | switchToLastApp(context); 586 | return; 587 | } else if (action.equals(SYSTEMUI_TASK_SETTINGS_PANEL)) { 588 | StatusBarHelper.expandSettingsPanel(); 589 | return; 590 | } else if (action.equals(SYSTEMUI_TASK_NOTIFICATION_PANEL)) { 591 | StatusBarHelper.expandNotificationPanel(); 592 | return; 593 | } else if (action.equals(SYSTEMUI_TASK_VOICE_SEARCH)) { 594 | launchVoiceSearch(context); 595 | return; 596 | } else if (action.equals(SYSTEMUI_TASK_APP_SEARCH)) { 597 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_SEARCH); 598 | return; 599 | } else if (action.equals(SYSTEMUI_TASK_MENU)) { 600 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_MENU); 601 | return; 602 | } else if (action.equals(SYSTEMUI_TASK_BACK)) { 603 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_BACK); 604 | return; 605 | } else if (action.equals(SYSTEMUI_TASK_HOME)) { 606 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_HOME); 607 | return; 608 | } else if (action.equals(SYSTEMUI_TASK_IME_SWITCHER)) { 609 | ((InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE)) 610 | .showInputMethodPicker(true /* showAuxiliarySubtypes */); 611 | return; 612 | } else if (action.equals(SYSTEMUI_TASK_STOP_SCREENPINNING)) { 613 | turnOffLockTask(); 614 | return; 615 | } else if (action.equals(SYSTEMUI_TASK_IME_NAVIGATION_RIGHT)) { 616 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_DPAD_RIGHT); 617 | return; 618 | } else if (action.equals(SYSTEMUI_TASK_IME_NAVIGATION_UP)) { 619 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_DPAD_UP); 620 | return; 621 | } else if (action.equals(SYSTEMUI_TASK_IME_NAVIGATION_DOWN)) { 622 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_DPAD_DOWN); 623 | return; 624 | } else if (action.equals(SYSTEMUI_TASK_IME_NAVIGATION_LEFT)) { 625 | triggerVirtualKeypress(context, KeyEvent.KEYCODE_DPAD_LEFT); 626 | return; 627 | } else if (action.equals(SYSTEMUI_TASK_MEDIA_PREVIOUS)) { 628 | dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_PREVIOUS, context); 629 | return; 630 | } else if (action.equals(SYSTEMUI_TASK_MEDIA_NEXT)) { 631 | dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_NEXT, context); 632 | return; 633 | } else if (action.equals(SYSTEMUI_TASK_MEDIA_PLAY_PAUSE)) { 634 | dispatchMediaKeyWithWakeLock(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, context); 635 | return; 636 | } else if (action.equals(SYSTEMUI_TASK_SOUNDMODE_VIB)) { 637 | AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 638 | if (am != null && ActivityManagerNative.isSystemReady()) { 639 | if (am.getRingerMode() != AudioManager.RINGER_MODE_VIBRATE) { 640 | am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE); 641 | Vibrator vib = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 642 | if (vib != null) { 643 | vib.vibrate(50); 644 | } 645 | } else { 646 | am.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 647 | ToneGenerator tg = new ToneGenerator( 648 | AudioManager.STREAM_NOTIFICATION, 649 | (int) (ToneGenerator.MAX_VOLUME * 0.85)); 650 | if (tg != null) { 651 | tg.startTone(ToneGenerator.TONE_PROP_BEEP); 652 | } 653 | } 654 | } 655 | return; 656 | } else if (action.equals(SYSTEMUI_TASK_SOUNDMODE_SILENT)) { 657 | AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 658 | if (am != null && ActivityManagerNative.isSystemReady()) { 659 | if (am.getRingerMode() != AudioManager.RINGER_MODE_SILENT) { 660 | am.setRingerMode(AudioManager.RINGER_MODE_SILENT); 661 | } else { 662 | am.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 663 | ToneGenerator tg = new ToneGenerator( 664 | AudioManager.STREAM_NOTIFICATION, 665 | (int) (ToneGenerator.MAX_VOLUME * 0.85)); 666 | if (tg != null) { 667 | tg.startTone(ToneGenerator.TONE_PROP_BEEP); 668 | } 669 | } 670 | } 671 | return; 672 | } else if (action.equals(SYSTEMUI_TASK_SOUNDMODE_VIB_SILENT)) { 673 | AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 674 | if (am != null && ActivityManagerNative.isSystemReady()) { 675 | if (am.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) { 676 | am.setRingerMode(AudioManager.RINGER_MODE_VIBRATE); 677 | Vibrator vib = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); 678 | if (vib != null) { 679 | vib.vibrate(50); 680 | } 681 | } else if (am.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) { 682 | am.setRingerMode(AudioManager.RINGER_MODE_SILENT); 683 | } else { 684 | am.setRingerMode(AudioManager.RINGER_MODE_NORMAL); 685 | ToneGenerator tg = new ToneGenerator( 686 | AudioManager.STREAM_NOTIFICATION, 687 | (int) (ToneGenerator.MAX_VOLUME * 0.85)); 688 | if (tg != null) { 689 | tg.startTone(ToneGenerator.TONE_PROP_BEEP); 690 | } 691 | } 692 | } 693 | return; 694 | } else if (action.equals(SYSTEMUI_TASK_CLEAR_NOTIFICATIONS)) { 695 | StatusBarHelper.clearAllNotifications(); 696 | return; 697 | } else if (action.equals(SYSTEMUI_TASK_VOLUME_PANEL)) { 698 | volumePanel(context); 699 | return; 700 | } else if (action.equals(SYSTEMUI_TASK_EDITING_SMARTBAR)) { 701 | StatusBarHelper.toggleNavigationEditor(); 702 | return; 703 | } else if (action.equals(SYSTEMUI_TASK_SPLIT_SCREEN)) { 704 | StatusBarHelper.splitScreen(); 705 | return; 706 | } else if (action.equals(SYSTEMUI_TASK_ONE_HANDED_MODE_LEFT)) { 707 | // toggleOneHandedMode(context, "left"); 708 | return; 709 | } else if (action.equals(SYSTEMUI_TASK_ONE_HANDED_MODE_RIGHT)) { 710 | // toggleOneHandedMode(context, "right"); 711 | return; 712 | } else if (action.equals(SYSTEMUI_TASK_ASSISTANT_SOUND_SEARCH)) { 713 | startAssistantSoundSearch(context); 714 | return; 715 | } 716 | } 717 | 718 | public static boolean isActionKeyEvent(String action) { 719 | if (action.equals(SYSTEMUI_TASK_HOME) 720 | || action.equals(SYSTEMUI_TASK_BACK) 721 | // || action.equals(SYSTEMUI_TASK_SEARCH) 722 | || action.equals(SYSTEMUI_TASK_MENU) 723 | // || action.equals(ActionConstants.ACTION_MENU_BIG) 724 | || action.equals(SYSTEMUI_TASK_NO_ACTION)) { 725 | return true; 726 | } 727 | return false; 728 | } 729 | 730 | private static void launchActivity(Context context, Intent intent) { 731 | try { 732 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); 733 | context.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT)); 734 | } catch (Exception e) { 735 | Log.i(TAG, "Unable to launch activity " + e); 736 | } 737 | } 738 | 739 | private static void switchToLastApp(Context context) { 740 | final ActivityManager am = 741 | (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); 742 | ActivityManager.RunningTaskInfo lastTask = getLastTask(context, am); 743 | 744 | if (lastTask != null) { 745 | am.moveTaskToFront(lastTask.id, ActivityManager.MOVE_TASK_NO_USER_ACTION, 746 | getAnimation(context).toBundle()); 747 | } 748 | } 749 | 750 | private static ActivityOptions getAnimation(Context context) { 751 | return ActivityOptions.makeCustomAnimation(context, 752 | com.android.internal.R.anim.du_app_in, 753 | com.android.internal.R.anim.du_app_out); 754 | } 755 | 756 | private static ActivityManager.RunningTaskInfo getLastTask(Context context, 757 | final ActivityManager am) { 758 | final String defaultHomePackage = resolveCurrentLauncherPackage(context); 759 | List tasks = am.getRunningTasks(5); 760 | 761 | for (int i = 1; i < tasks.size(); i++) { 762 | String packageName = tasks.get(i).topActivity.getPackageName(); 763 | if (!packageName.equals(defaultHomePackage) 764 | && !packageName.equals(context.getPackageName()) 765 | && !packageName.equals(SYSTEMUI)) { 766 | return tasks.get(i); 767 | } 768 | } 769 | return null; 770 | } 771 | 772 | private static String resolveCurrentLauncherPackage(Context context) { 773 | final Intent launcherIntent = new Intent(Intent.ACTION_MAIN) 774 | .addCategory(Intent.CATEGORY_HOME); 775 | final PackageManager pm = context.getPackageManager(); 776 | final ResolveInfo launcherInfo = pm.resolveActivity(launcherIntent, 0); 777 | return launcherInfo.activityInfo.packageName; 778 | } 779 | 780 | private static void sendCloseSystemWindows(String reason) { 781 | if (ActivityManagerNative.isSystemReady()) { 782 | try { 783 | ActivityManagerNative.getDefault().closeSystemDialogs(reason); 784 | } catch (RemoteException e) { 785 | } 786 | } 787 | } 788 | 789 | 790 | private static void toggleExpandedDesktop(Context context) { 791 | ContentResolver cr = context.getContentResolver(); 792 | String newVal = ""; 793 | String currentVal = Settings.Global.getString(cr, Settings.Global.POLICY_CONTROL); 794 | if (currentVal == null) { 795 | currentVal = newVal; 796 | } 797 | if ("".equals(currentVal)) { 798 | newVal = "immersive.full=*"; 799 | } 800 | Settings.Global.putString(cr, Settings.Global.POLICY_CONTROL, newVal); 801 | if (newVal.equals("")) { 802 | WindowManagerPolicyControl.reloadFromSetting(context); 803 | } 804 | } 805 | 806 | private static void launchVoiceSearch(Context context) { 807 | sendCloseSystemWindows("assist"); 808 | // launch the search activity 809 | Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS); 810 | try { 811 | // TODO: This only stops the factory-installed search manager. 812 | // Need to formalize an API to handle others 813 | SearchManager searchManager = (SearchManager) context 814 | .getSystemService(Context.SEARCH_SERVICE); 815 | if (searchManager != null) { 816 | searchManager.stopSearch(); 817 | } 818 | launchActivity(context, intent); 819 | } catch (ActivityNotFoundException e) { 820 | Slog.w(TAG, "No assist activity installed", e); 821 | } 822 | } 823 | 824 | private static void dispatchMediaKeyWithWakeLock(int keycode, Context context) { 825 | if (ActivityManagerNative.isSystemReady()) { 826 | KeyEvent event = new KeyEvent(SystemClock.uptimeMillis(), 827 | SystemClock.uptimeMillis(), KeyEvent.ACTION_DOWN, keycode, 0); 828 | MediaSessionLegacyHelper.getHelper(context).sendMediaButtonEvent(event, true); 829 | event = KeyEvent.changeAction(event, KeyEvent.ACTION_UP); 830 | MediaSessionLegacyHelper.getHelper(context).sendMediaButtonEvent(event, true); 831 | } 832 | } 833 | 834 | private static void triggerVirtualKeypress(Context context, final int keyCode) { 835 | final InputManager im = InputManager.getInstance(); 836 | final long now = SystemClock.uptimeMillis(); 837 | int downflags = 0; 838 | 839 | if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT 840 | || keyCode == KeyEvent.KEYCODE_DPAD_RIGHT 841 | || keyCode == KeyEvent.KEYCODE_DPAD_UP 842 | || keyCode == KeyEvent.KEYCODE_DPAD_DOWN) { 843 | downflags = KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE; 844 | } else { 845 | downflags = KeyEvent.FLAG_FROM_SYSTEM; 846 | } 847 | 848 | final KeyEvent downEvent = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, 849 | keyCode, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0, 850 | downflags, InputDevice.SOURCE_KEYBOARD); 851 | final KeyEvent upEvent = KeyEvent.changeAction(downEvent, KeyEvent.ACTION_UP); 852 | final Handler handler = new Handler(Looper.getMainLooper()); 853 | 854 | final Runnable downRunnable = new Runnable() { 855 | @Override 856 | public void run() { 857 | im.injectInputEvent(downEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 858 | } 859 | }; 860 | 861 | final Runnable upRunnable = new Runnable() { 862 | @Override 863 | public void run() { 864 | im.injectInputEvent(upEvent, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC); 865 | } 866 | }; 867 | 868 | handler.post(downRunnable); 869 | handler.postDelayed(upRunnable, 10); 870 | } 871 | 872 | private static void launchCamera(Context context) { 873 | Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); 874 | PackageManager pm = context.getPackageManager(); 875 | final ResolveInfo mInfo = pm.resolveActivity(i, 0); 876 | Intent intent = new Intent().setComponent(new ComponentName(mInfo.activityInfo.packageName, 877 | mInfo.activityInfo.name)); 878 | launchActivity(context, intent); 879 | } 880 | 881 | private static void toggleWifi(Context context) { 882 | WifiManager wfm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 883 | wfm.setWifiEnabled(!wfm.isWifiEnabled()); 884 | } 885 | 886 | private static void toggleBluetooth() { 887 | BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 888 | boolean enabled = bluetoothAdapter.isEnabled(); 889 | if (enabled) { 890 | bluetoothAdapter.disable(); 891 | } else { 892 | bluetoothAdapter.enable(); 893 | } 894 | } 895 | 896 | private static void toggleWifiAP(Context context) { 897 | final ContentResolver cr = context.getContentResolver(); 898 | WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 899 | final ConnectivityManager mConnectivityManager; 900 | mConnectivityManager = (ConnectivityManager) context.getSystemService( 901 | Context.CONNECTIVITY_SERVICE); 902 | int state = wm.getWifiApState(); 903 | boolean enabled = false; 904 | switch (state) { 905 | case WifiManager.WIFI_AP_STATE_ENABLING: 906 | case WifiManager.WIFI_AP_STATE_ENABLED: 907 | enabled = false; 908 | break; 909 | case WifiManager.WIFI_AP_STATE_DISABLING: 910 | case WifiManager.WIFI_AP_STATE_DISABLED: 911 | enabled = true; 912 | break; 913 | } 914 | 915 | // Turn on the Wifi AP 916 | if (enabled) { 917 | OnStartTetheringCallback callback = new OnStartTetheringCallback(); 918 | mConnectivityManager.startTethering( 919 | ConnectivityManager.TETHERING_WIFI, false, callback); 920 | } else { 921 | mConnectivityManager.stopTethering(ConnectivityManager.TETHERING_WIFI); 922 | } 923 | } 924 | 925 | static final class OnStartTetheringCallback extends 926 | ConnectivityManager.OnStartTetheringCallback { 927 | @Override 928 | public void onTetheringStarted() {} 929 | @Override 930 | public void onTetheringFailed() { 931 | // TODO: Show error. 932 | } 933 | } 934 | 935 | private static void sendCommandToWindowManager(Intent intent) { 936 | IWindowManager wm = WindowManagerGlobal.getWindowManagerService(); 937 | try { 938 | wm.sendCustomAction(intent); 939 | } catch (RemoteException e) { 940 | e.printStackTrace(); 941 | } 942 | } 943 | 944 | private static void killProcess(Context context) { 945 | if (context.checkCallingOrSelfPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) == PackageManager.PERMISSION_GRANTED 946 | && !isLockTaskOn()) { 947 | try { 948 | PackageManager packageManager = context.getPackageManager(); 949 | final Intent intent = new Intent(Intent.ACTION_MAIN); 950 | String defaultHomePackage = "com.android.launcher"; 951 | intent.addCategory(Intent.CATEGORY_HOME); 952 | final ResolveInfo res = packageManager.resolveActivity(intent, 0); 953 | if (res.activityInfo != null 954 | && !res.activityInfo.packageName.equals("android")) { 955 | defaultHomePackage = res.activityInfo.packageName; 956 | } 957 | 958 | // Use UsageStats to determine foreground app 959 | UsageStatsManager usageStatsManager = (UsageStatsManager) 960 | context.getSystemService(Context.USAGE_STATS_SERVICE); 961 | long current = System.currentTimeMillis(); 962 | long past = current - (1000 * 60 * 60); // uses snapshot of usage over past 60 minutes 963 | 964 | // Get the list, then sort it chronilogically so most recent usage is at start of list 965 | List recentApps = usageStatsManager.queryUsageStats( 966 | UsageStatsManager.INTERVAL_DAILY, past, current); 967 | Collections.sort(recentApps, new Comparator() { 968 | @Override 969 | public int compare(UsageStats lhs, UsageStats rhs) { 970 | long timeLHS = lhs.getLastTimeUsed(); 971 | long timeRHS = rhs.getLastTimeUsed(); 972 | if (timeLHS > timeRHS) { 973 | return -1; 974 | } else if (timeLHS < timeRHS) { 975 | return 1; 976 | } 977 | return 0; 978 | } 979 | }); 980 | 981 | IActivityManager iam = ActivityManagerNative.getDefault(); 982 | // this may not be needed due to !isLockTaskOn() in entry if 983 | //if (am.getLockTaskModeState() != ActivityManager.LOCK_TASK_MODE_NONE) return; 984 | 985 | // Look for most recent usagestat with lastevent == 1 and grab package name 986 | // ...this seems to map to the UsageEvents.Event.MOVE_TO_FOREGROUND 987 | String pkg = null; 988 | for (int i = 0; i < recentApps.size(); i++) { 989 | UsageStats mostRecent = recentApps.get(i); 990 | if (mostRecent.mLastEvent == 1) { 991 | pkg = mostRecent.mPackageName; 992 | break; 993 | } 994 | } 995 | 996 | if (pkg != null && !pkg.equals("com.android.systemui") 997 | && !pkg.equals(defaultHomePackage)) { 998 | 999 | // Restore home screen stack before killing the app 1000 | Intent home = new Intent(Intent.ACTION_MAIN, null); 1001 | home.addCategory(Intent.CATEGORY_HOME); 1002 | home.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1003 | | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); 1004 | context.startActivity(home); 1005 | 1006 | // Kill the app 1007 | iam.forceStopPackage(pkg, UserHandle.USER_CURRENT); 1008 | 1009 | // Remove killed app from Recents 1010 | final ActivityManager am = (ActivityManager) 1011 | context.getSystemService(Context.ACTIVITY_SERVICE); 1012 | final List recentTasks = 1013 | am.getRecentTasksForUser(ActivityManager.getMaxRecentTasksStatic(), 1014 | ActivityManager.RECENT_IGNORE_HOME_AND_RECENTS_STACK_TASKS 1015 | | ActivityManager.RECENT_INGORE_PINNED_STACK_TASKS 1016 | | ActivityManager.RECENT_IGNORE_UNAVAILABLE 1017 | | ActivityManager.RECENT_INCLUDE_PROFILES, 1018 | UserHandle.CURRENT.getIdentifier()); 1019 | final int size = recentTasks.size(); 1020 | for (int i = 0; i < size; i++) { 1021 | ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i); 1022 | if (recentInfo.baseIntent.getComponent().getPackageName().equals(pkg)) { 1023 | int taskid = recentInfo.persistentId; 1024 | am.removeTask(taskid); 1025 | } 1026 | } 1027 | 1028 | String pkgName; 1029 | try { 1030 | pkgName = (String) packageManager.getApplicationLabel( 1031 | packageManager.getApplicationInfo(pkg, PackageManager.GET_META_DATA)); 1032 | } catch (PackageManager.NameNotFoundException e) { 1033 | // Just use pkg if issues getting appName 1034 | pkgName = pkg; 1035 | } 1036 | 1037 | Resources systemUIRes = DUActionUtils.getResourcesForPackage(context, DUActionUtils.PACKAGE_SYSTEMUI); 1038 | int ident = systemUIRes.getIdentifier("app_killed_message", DUActionUtils.STRING, DUActionUtils.PACKAGE_SYSTEMUI); 1039 | String toastMsg = systemUIRes.getString(ident, pkgName); 1040 | Toast.makeText(context, toastMsg, Toast.LENGTH_SHORT).show(); 1041 | return; 1042 | } else { 1043 | // make a "didnt kill anything" toast? 1044 | return; 1045 | } 1046 | } catch (RemoteException remoteException) { 1047 | Log.d("ActionHandler", "Caller cannot kill processes, aborting"); 1048 | } 1049 | } else { 1050 | Log.d("ActionHandler", "Caller cannot kill processes, aborting"); 1051 | } 1052 | } 1053 | 1054 | private static boolean isPackageLiveWalls(Context ctx, String pkg) { 1055 | if (ctx == null || pkg == null) { 1056 | return false; 1057 | } 1058 | List liveWallsList = ctx.getPackageManager().queryIntentServices( 1059 | new Intent(WallpaperService.SERVICE_INTERFACE), 1060 | PackageManager.GET_META_DATA); 1061 | if (liveWallsList == null) { 1062 | return false; 1063 | } 1064 | for (ResolveInfo info : liveWallsList) { 1065 | if (info.serviceInfo != null) { 1066 | String packageName = info.serviceInfo.packageName; 1067 | if (TextUtils.equals(pkg, packageName)) { 1068 | return true; 1069 | } 1070 | } 1071 | } 1072 | return false; 1073 | } 1074 | 1075 | private static void screenOff(Context context) { 1076 | PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 1077 | pm.goToSleep(SystemClock.uptimeMillis()); 1078 | } 1079 | 1080 | private static void launchAssistAction(Context context) { 1081 | sendCloseSystemWindows("assist"); 1082 | Intent intent = ((SearchManager) context.getSystemService(Context.SEARCH_SERVICE)) 1083 | .getAssistIntent(true); 1084 | if (intent != null) { 1085 | intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK 1086 | | Intent.FLAG_ACTIVITY_SINGLE_TOP 1087 | | Intent.FLAG_ACTIVITY_CLEAR_TOP); 1088 | try { 1089 | context.startActivityAsUser(intent, UserHandle.CURRENT); 1090 | } catch (ActivityNotFoundException e) { 1091 | Slog.w(TAG, "No activity to handle assist action.", e); 1092 | } 1093 | } 1094 | } 1095 | 1096 | public static void turnOffLockTask() { 1097 | try { 1098 | ActivityManagerNative.getDefault().stopLockTaskMode(); 1099 | } catch (Exception e) { 1100 | } 1101 | } 1102 | 1103 | public static boolean isLockTaskOn() { 1104 | try { 1105 | return ActivityManagerNative.getDefault().isInLockTaskMode(); 1106 | } catch (Exception e) { 1107 | } 1108 | return false; 1109 | } 1110 | 1111 | public static void volumePanel(Context context) { 1112 | AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 1113 | am.adjustVolume(AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI); 1114 | } 1115 | 1116 | /* 1117 | private static void toggleOneHandedMode(Context context, String direction) { 1118 | String str = Settings.Global.getString(context.getContentResolver(), Settings.Global.SINGLE_HAND_MODE); 1119 | 1120 | if (TextUtils.isEmpty(str)) 1121 | Settings.Global.putString(context.getContentResolver(), Settings.Global.SINGLE_HAND_MODE, direction); 1122 | else 1123 | Settings.Global.putString(context.getContentResolver(), Settings.Global.SINGLE_HAND_MODE, ""); 1124 | } 1125 | */ 1126 | 1127 | public static void startAssistantSoundSearch(Context context) { 1128 | Intent intent = new Intent(Intent.ACTION_MAIN); 1129 | intent.setAction("com.google.android.googlequicksearchbox.MUSIC_SEARCH"); 1130 | context.startActivity(intent); 1131 | } 1132 | } 1133 | --------------------------------------------------------------------------------