AppOpsState.java revision 7d3a4c160cac37b72aa9149952358df4a3912cfb
118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn/** 218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * Copyright (C) 2013 The Android Open Source Project 318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * 418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License"); you may not 518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * use this file except in compliance with the License. You may obtain a copy 618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * of the License at 718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * 818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * http://www.apache.org/licenses/LICENSE-2.0 918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * 1018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * Unless required by applicable law or agreed to in writing, software 1118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 1218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 1318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * License for the specific language governing permissions and limitations 1418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * under the License. 1518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn */ 1618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 1718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornpackage com.android.settings.applications; 1818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 1918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.app.AppOpsManager; 2018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.content.Context; 2118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.content.pm.ApplicationInfo; 2218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.content.pm.PackageInfo; 2318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.content.pm.PackageManager; 2418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.content.pm.PackageManager.NameNotFoundException; 2518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.content.res.Resources; 2618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.graphics.drawable.Drawable; 2718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.os.Parcel; 2818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.os.Parcelable; 2918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport android.text.format.DateUtils; 3018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 310dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.util.Log; 320dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackbornimport android.util.SparseArray; 3318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport com.android.settings.R; 3418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 3518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport java.io.File; 3618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport java.text.Collator; 3718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport java.util.ArrayList; 3818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport java.util.Collections; 3918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport java.util.Comparator; 4018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport java.util.HashMap; 4118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornimport java.util.List; 4218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 4318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackbornpublic class AppOpsState { 440dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn static final String TAG = "AppOpsState"; 450dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn static final boolean DEBUG = false; 460dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 4718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn final Context mContext; 4818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn final AppOpsManager mAppOps; 4918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn final PackageManager mPm; 500dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn final CharSequence[] mOpNames; 5118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 5218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn List<AppOpEntry> mApps; 5318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 5418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public AppOpsState(Context context) { 5518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mContext = context; 5618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE); 5718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mPm = context.getPackageManager(); 580dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn mOpNames = context.getResources().getTextArray(R.array.app_ops_names); 5918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 6018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 6118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static class OpsTemplate implements Parcelable { 6218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public final int[] ops; 6318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 640dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn public OpsTemplate(int[] _ops) { 6518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn ops = _ops; 6618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 6718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 6818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn OpsTemplate(Parcel src) { 6918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn ops = src.createIntArray(); 7018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 7118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 7218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn @Override 7318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public int describeContents() { 7418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return 0; 7518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 7618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 7718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn @Override 7818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public void writeToParcel(Parcel dest, int flags) { 7918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn dest.writeIntArray(ops); 8018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 8118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 8218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static final Creator<OpsTemplate> CREATOR = new Creator<OpsTemplate>() { 8318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn @Override public OpsTemplate createFromParcel(Parcel source) { 8418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return new OpsTemplate(source); 8518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 8618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 8718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn @Override public OpsTemplate[] newArray(int size) { 8818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return new OpsTemplate[size]; 8918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 9018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn }; 9118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 9218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 9318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static final OpsTemplate LOCATION_TEMPLATE = new OpsTemplate( 9418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn new int[] { AppOpsManager.OP_COARSE_LOCATION, 9518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn AppOpsManager.OP_FINE_LOCATION, 960dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.OP_GPS, 970dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.OP_WIFI_SCAN } 9818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn ); 9918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 10018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static final OpsTemplate PERSONAL_TEMPLATE = new OpsTemplate( 10118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn new int[] { AppOpsManager.OP_READ_CONTACTS, 10218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn AppOpsManager.OP_WRITE_CONTACTS, 10318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn AppOpsManager.OP_READ_CALL_LOG, 1040dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.OP_WRITE_CALL_LOG, 1050dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.OP_READ_CALENDAR, 1060dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.OP_WRITE_CALENDAR } 10718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn ); 10818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 10918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static final OpsTemplate DEVICE_TEMPLATE = new OpsTemplate( 11018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn new int[] { AppOpsManager.OP_VIBRATE } 11118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn ); 11218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 1130dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn public static final OpsTemplate[] ALL_TEMPLATES = new OpsTemplate[] { 1140dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn LOCATION_TEMPLATE, PERSONAL_TEMPLATE, DEVICE_TEMPLATE 1150dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn }; 1160dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 11718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn /** 11818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * This class holds the per-item data in our Loader. 11918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn */ 12018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static class AppEntry { 12118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private final AppOpsState mState; 12218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private final ApplicationInfo mInfo; 12318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private final File mApkFile; 1240dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn private final SparseArray<AppOpsManager.OpEntry> mOps 1250dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn = new SparseArray<AppOpsManager.OpEntry>(); 12618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private String mLabel; 12718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private Drawable mIcon; 12818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private boolean mMounted; 12918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 13018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public AppEntry(AppOpsState state, ApplicationInfo info) { 13118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mState = state; 13218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mInfo = info; 13318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mApkFile = new File(info.sourceDir); 13418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 13518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 1360dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn public void addOp(AppOpsManager.OpEntry op) { 1370dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn mOps.put(op.getOp(), op); 1380dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 1390dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 1400dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn public boolean hasOp(int op) { 1410dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return mOps.indexOfKey(op) >= 0; 1420dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 1430dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 14418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public ApplicationInfo getApplicationInfo() { 14518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mInfo; 14618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 14718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 14818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public String getLabel() { 14918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mLabel; 15018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 15118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 15218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public Drawable getIcon() { 15318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (mIcon == null) { 15418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (mApkFile.exists()) { 15518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mIcon = mInfo.loadIcon(mState.mPm); 15618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mIcon; 15718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } else { 15818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mMounted = false; 15918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 16018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } else if (!mMounted) { 16118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn // If the app wasn't mounted but is now mounted, reload 16218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn // its icon. 16318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (mApkFile.exists()) { 16418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mMounted = true; 16518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mIcon = mInfo.loadIcon(mState.mPm); 16618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mIcon; 16718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 16818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } else { 16918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mIcon; 17018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 17118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 17218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mState.mContext.getResources().getDrawable( 17318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn android.R.drawable.sym_def_app_icon); 17418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 17518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 17618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn @Override public String toString() { 17718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mLabel; 17818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 17918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 18018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn void loadLabel(Context context) { 18118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (mLabel == null || !mMounted) { 18218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (!mApkFile.exists()) { 18318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mMounted = false; 18418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mLabel = mInfo.packageName; 18518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } else { 18618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mMounted = true; 18718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn CharSequence label = mInfo.loadLabel(context.getPackageManager()); 18818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mLabel = label != null ? label.toString() : mInfo.packageName; 18918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 19018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 19118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 19218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 19318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 19418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn /** 19518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * This class holds the per-item data in our Loader. 19618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn */ 19718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static class AppOpEntry { 19818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private final AppOpsManager.PackageOps mPkgOps; 19918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private final ArrayList<AppOpsManager.OpEntry> mOps 20018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn = new ArrayList<AppOpsManager.OpEntry>(); 20118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private final AppEntry mApp; 20218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 20318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public AppOpEntry(AppOpsManager.PackageOps pkg, AppOpsManager.OpEntry op, AppEntry app) { 20418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mPkgOps = pkg; 20518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mApp = app; 2060dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn mApp.addOp(op); 2070dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn mOps.add(op); 20818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 20918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 21018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public void addOp(AppOpsManager.OpEntry op) { 2110dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn mApp.addOp(op); 21218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn for (int i=0; i<mOps.size(); i++) { 21318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn AppOpsManager.OpEntry pos = mOps.get(i); 21418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (pos.isRunning() != op.isRunning()) { 21518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (op.isRunning()) { 21618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mOps.add(i, op); 21718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return; 21818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 2190dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn continue; 22018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 2210dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (pos.getTime() < op.getTime()) { 22218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mOps.add(i, op); 22318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return; 22418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 22518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 22618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn mOps.add(op); 22718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 22818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 22918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public AppEntry getAppEntry() { 23018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mApp; 23118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 23218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 23318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public AppOpsManager.PackageOps getPackageOps() { 23418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mPkgOps; 23518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 23618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 23718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public int getNumOpEntry() { 23818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mOps.size(); 23918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 24018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 24118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public AppOpsManager.OpEntry getOpEntry(int pos) { 24218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mOps.get(pos); 24318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 24418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 2450dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn public CharSequence getLabelText(AppOpsState state) { 24618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (getNumOpEntry() == 1) { 2470dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return state.mOpNames[getOpEntry(0).getOp()]; 24818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } else { 24918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn StringBuilder builder = new StringBuilder(); 25018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn for (int i=0; i<getNumOpEntry(); i++) { 25118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (i > 0) { 25218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn builder.append(", "); 25318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 2540dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn builder.append(state.mOpNames[getOpEntry(i).getOp()]); 25518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 25618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return builder.toString(); 25718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 25818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 25918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 26018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public CharSequence getTimeText(Resources res) { 26118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (isRunning()) { 26218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return res.getText(R.string.app_ops_running); 26318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 26418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (getTime() > 0) { 26518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return DateUtils.getRelativeTimeSpanString(getTime(), 26618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn System.currentTimeMillis(), 26718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn DateUtils.MINUTE_IN_MILLIS, 26818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn DateUtils.FORMAT_ABBREV_RELATIVE); 26918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 27018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return ""; 27118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 27218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 27318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public boolean isRunning() { 27418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mOps.get(0).isRunning(); 27518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 27618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 27718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public long getTime() { 27818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mOps.get(0).getTime(); 27918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 28018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 28118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn @Override public String toString() { 28218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return mApp.getLabel(); 28318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 28418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 28518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 28618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn /** 28718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn * Perform alphabetical comparison of application entry objects. 28818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn */ 28918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public static final Comparator<AppOpEntry> APP_OP_COMPARATOR = new Comparator<AppOpEntry>() { 29018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private final Collator sCollator = Collator.getInstance(); 29118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn @Override 29218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public int compare(AppOpEntry object1, AppOpEntry object2) { 29318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (object1.isRunning() != object2.isRunning()) { 29418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn // Currently running ops go first. 29518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return object1.isRunning() ? -1 : 1; 29618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 29718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (object1.getTime() != object2.getTime()) { 29818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn // More recent times go first. 29918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return object1.getTime() > object2.getTime() ? -1 : 1; 30018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 30118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return sCollator.compare(object1.getAppEntry().getLabel(), 30218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn object2.getAppEntry().getLabel()); 30318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 30418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn }; 30518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 30618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn private void addOp(List<AppOpEntry> entries, AppOpsManager.PackageOps pkgOps, 30718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn AppEntry appEntry, AppOpsManager.OpEntry opEntry) { 30818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (entries.size() > 0) { 30918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn AppOpEntry last = entries.get(entries.size()-1); 31018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (last.getAppEntry() == appEntry) { 31118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn boolean lastExe = last.getTime() != 0; 31218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn boolean entryExe = opEntry.getTime() != 0; 31318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (lastExe == entryExe) { 3140dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package " 3150dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn + pkgOps.getPackageName() + ": append to " + last); 31618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn last.addOp(opEntry); 31718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return; 31818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 31918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 32018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 32118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn AppOpEntry entry = new AppOpEntry(pkgOps, opEntry, appEntry); 3220dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package " 3230dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn + pkgOps.getPackageName() + ": making new " + entry); 32418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn entries.add(entry); 32518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 32618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 32718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public List<AppOpEntry> buildState(OpsTemplate tpl) { 32818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return buildState(tpl, 0, null); 32918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 33018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 3310dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn private AppEntry getAppEntry(final Context context, final HashMap<String, AppEntry> appEntries, 3320dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn final String packageName, ApplicationInfo appInfo) { 3330dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppEntry appEntry = appEntries.get(packageName); 3340dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (appEntry == null) { 3350dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (appInfo == null) { 3360dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn try { 3370dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn appInfo = mPm.getApplicationInfo(packageName, 3380dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn PackageManager.GET_DISABLED_COMPONENTS 3390dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn | PackageManager.GET_UNINSTALLED_PACKAGES); 3400dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } catch (PackageManager.NameNotFoundException e) { 3410dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn Log.w(TAG, "Unable to find info for package " + packageName); 3420dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return null; 3430dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 3440dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 3450dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn appEntry = new AppEntry(this, appInfo); 3460dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn appEntry.loadLabel(context); 3470dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn appEntries.put(packageName, appEntry); 3480dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 3490dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return appEntry; 3500dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 3510dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 35218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn public List<AppOpEntry> buildState(OpsTemplate tpl, int uid, String packageName) { 35318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn final Context context = mContext; 35418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 35518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn final HashMap<String, AppEntry> appEntries = new HashMap<String, AppEntry>(); 3560dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn List<AppOpEntry> entries = new ArrayList<AppOpEntry>(); 3570dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 3580dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn ArrayList<String> perms = new ArrayList<String>(); 3590dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn ArrayList<Integer> permOps = new ArrayList<Integer>(); 3600dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn for (int i=0; i<tpl.ops.length; i++) { 3610dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn String perm = AppOpsManager.opToPermission(tpl.ops[i]); 3627d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (perm != null && !perms.contains(perm)) { 3630dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn perms.add(perm); 3640dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn permOps.add(tpl.ops[i]); 3650dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 3660dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 36718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 36818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn List<AppOpsManager.PackageOps> pkgs; 36918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn if (packageName != null) { 37018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn pkgs = mAppOps.getOpsForPackage(uid, packageName, tpl.ops); 37118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } else { 37218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn pkgs = mAppOps.getPackagesForOps(tpl.ops); 37318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 3740dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 3750dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (pkgs != null) { 3760dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn for (int i=0; i<pkgs.size(); i++) { 3770dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.PackageOps pkgOps = pkgs.get(i); 3780dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppEntry appEntry = getAppEntry(context, appEntries, pkgOps.getPackageName(), null); 3790dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (appEntry == null) { 3800dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn continue; 3810dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 3820dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn for (int j=0; j<pkgOps.getOps().size(); j++) { 3830dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.OpEntry opEntry = pkgOps.getOps().get(j); 3840dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn addOp(entries, pkgOps, appEntry, opEntry); 38518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 38618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 38718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 38818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 3890dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn List<PackageInfo> apps; 3900dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (packageName != null) { 3910dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn apps = new ArrayList<PackageInfo>(); 3920dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn try { 3930dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn PackageInfo pi = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS); 3940dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn apps.add(pi); 3950dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } catch (NameNotFoundException e) { 39618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 3970dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } else { 3980dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn String[] permsArray = new String[perms.size()]; 3990dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn perms.toArray(permsArray); 4000dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn apps = mPm.getPackagesHoldingPermissions(permsArray, 0); 4010dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 4020dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn for (int i=0; i<apps.size(); i++) { 4030dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn PackageInfo appInfo = apps.get(i); 4040dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppEntry appEntry = getAppEntry(context, appEntries, appInfo.packageName, 4050dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn appInfo.applicationInfo); 4060dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (appEntry == null) { 4070dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn continue; 4080dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 4090dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn List<AppOpsManager.OpEntry> dummyOps = null; 4100dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn AppOpsManager.PackageOps pkgOps = null; 4117d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (appInfo.requestedPermissions != null) { 4127d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler for (int j=0; j<appInfo.requestedPermissions.length; j++) { 4137d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (appInfo.requestedPermissionsFlags != null) { 4147d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if ((appInfo.requestedPermissionsFlags[j] 4157d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler & PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0) { 4167d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (DEBUG) Log.d(TAG, "Pkg " + appInfo.packageName + " perm " 4177d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler + appInfo.requestedPermissions[j] + " not granted; skipping"); 4187d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler break; 4197d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler } 42018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 4217d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (DEBUG) Log.d(TAG, "Pkg " + appInfo.packageName + ": requested perm " 4227d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler + appInfo.requestedPermissions[j]); 4237d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler for (int k=0; k<perms.size(); k++) { 4247d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (!perms.get(k).equals(appInfo.requestedPermissions[j])) { 4257d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler continue; 4267d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler } 4277d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (DEBUG) Log.d(TAG, "Pkg " + appInfo.packageName + " perm " + perms.get(k) 4287d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler + " has op " + permOps.get(k) + ": " + appEntry.hasOp(permOps.get(k))); 4297d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (appEntry.hasOp(permOps.get(k))) { 4307d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler continue; 4317d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler } 4327d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler if (dummyOps == null) { 4337d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler dummyOps = new ArrayList<AppOpsManager.OpEntry>(); 4347d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler pkgOps = new AppOpsManager.PackageOps( 4357d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler appInfo.packageName, appInfo.applicationInfo.uid, dummyOps); 4367d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler 4377d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler } 4387d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry( 4397d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler permOps.get(k), AppOpsManager.MODE_ALLOWED, 0, 0, 0); 4407d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler dummyOps.add(opEntry); 4417d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler addOp(entries, pkgOps, appEntry, opEntry); 4420dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 4430dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 44418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 44518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 44618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 44718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn // Sort the list. 44818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn Collections.sort(entries, APP_OP_COMPARATOR); 44918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn 45018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn // Done! 45118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn return entries; 45218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn } 4530dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 4540dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn public CharSequence getLabelText(AppOpsManager.OpEntry op) { 4550dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return mOpNames[op.getOp()]; 4560dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 4570dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 4580dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn public CharSequence getTimeText(AppOpsManager.OpEntry op) { 4590dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (op.isRunning()) { 4600dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return mContext.getResources().getText(R.string.app_ops_running); 4610dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 4620dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn if (op.getTime() > 0) { 4630dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return DateUtils.getRelativeTimeSpanString(op.getTime(), 4640dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn System.currentTimeMillis(), 4650dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn DateUtils.MINUTE_IN_MILLIS, 4660dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn DateUtils.FORMAT_ABBREV_RELATIVE); 4670dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 4680dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn return mContext.getResources().getText(R.string.app_ops_never_used); 4690dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn } 4700dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn 47118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn} 472