AppOpsState.java revision ec74da60cda5d0d7d1901e20a5a7806ef4cf387f
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;
508b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn    final CharSequence[] mOpSummaries;
518b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn    final CharSequence[] mOpLabels;
5218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
5318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    List<AppOpEntry> mApps;
5418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
5518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public AppOpsState(Context context) {
5618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        mContext = context;
5718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
5818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        mPm = context.getPackageManager();
598b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        mOpSummaries = context.getResources().getTextArray(R.array.app_ops_summaries);
608b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        mOpLabels = context.getResources().getTextArray(R.array.app_ops_labels);
6118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    }
6218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
6318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public static class OpsTemplate implements Parcelable {
6418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public final int[] ops;
6527daaab633a80be50863e6539e947db674090662Dianne Hackborn        public final boolean[] showPerms;
6618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
6727daaab633a80be50863e6539e947db674090662Dianne Hackborn        public OpsTemplate(int[] _ops, boolean[] _showPerms) {
6818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            ops = _ops;
6927daaab633a80be50863e6539e947db674090662Dianne Hackborn            showPerms = _showPerms;
7018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
7118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
7218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        OpsTemplate(Parcel src) {
7318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            ops = src.createIntArray();
7427daaab633a80be50863e6539e947db674090662Dianne Hackborn            showPerms = src.createBooleanArray();
7518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
7618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
7718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        @Override
7818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public int describeContents() {
7918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return 0;
8018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
8118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
8218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        @Override
8318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public void writeToParcel(Parcel dest, int flags) {
8418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            dest.writeIntArray(ops);
8527daaab633a80be50863e6539e947db674090662Dianne Hackborn            dest.writeBooleanArray(showPerms);
8618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
8718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
8818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public static final Creator<OpsTemplate> CREATOR = new Creator<OpsTemplate>() {
8918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            @Override public OpsTemplate createFromParcel(Parcel source) {
9018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return new OpsTemplate(source);
9118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
9218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
9318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            @Override public OpsTemplate[] newArray(int size) {
9418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return new OpsTemplate[size];
9518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
9618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        };
9718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    }
9818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
9918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public static final OpsTemplate LOCATION_TEMPLATE = new OpsTemplate(
10018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            new int[] { AppOpsManager.OP_COARSE_LOCATION,
10118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    AppOpsManager.OP_FINE_LOCATION,
1020dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    AppOpsManager.OP_GPS,
10327daaab633a80be50863e6539e947db674090662Dianne Hackborn                    AppOpsManager.OP_WIFI_SCAN,
10427daaab633a80be50863e6539e947db674090662Dianne Hackborn                    AppOpsManager.OP_NEIGHBORING_CELLS },
10527daaab633a80be50863e6539e947db674090662Dianne Hackborn            new boolean[] { true,
10627daaab633a80be50863e6539e947db674090662Dianne Hackborn                    true,
10727daaab633a80be50863e6539e947db674090662Dianne Hackborn                    false,
10827daaab633a80be50863e6539e947db674090662Dianne Hackborn                    false,
10927daaab633a80be50863e6539e947db674090662Dianne Hackborn                    false }
11018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            );
11118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
11218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public static final OpsTemplate PERSONAL_TEMPLATE = new OpsTemplate(
11318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            new int[] { AppOpsManager.OP_READ_CONTACTS,
11418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    AppOpsManager.OP_WRITE_CONTACTS,
11518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    AppOpsManager.OP_READ_CALL_LOG,
1160dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    AppOpsManager.OP_WRITE_CALL_LOG,
1170dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    AppOpsManager.OP_READ_CALENDAR,
118782c3de338d6b4ac8280e0686b8a4b39c0e3f70fDianne Hackborn                    AppOpsManager.OP_WRITE_CALENDAR,
119782c3de338d6b4ac8280e0686b8a4b39c0e3f70fDianne Hackborn                    AppOpsManager.OP_READ_CLIPBOARD,
120782c3de338d6b4ac8280e0686b8a4b39c0e3f70fDianne Hackborn                    AppOpsManager.OP_WRITE_CLIPBOARD },
12127daaab633a80be50863e6539e947db674090662Dianne Hackborn            new boolean[] { true,
12227daaab633a80be50863e6539e947db674090662Dianne Hackborn                    true,
12327daaab633a80be50863e6539e947db674090662Dianne Hackborn                    true,
12427daaab633a80be50863e6539e947db674090662Dianne Hackborn                    true,
12527daaab633a80be50863e6539e947db674090662Dianne Hackborn                    true,
126782c3de338d6b4ac8280e0686b8a4b39c0e3f70fDianne Hackborn                    true,
127782c3de338d6b4ac8280e0686b8a4b39c0e3f70fDianne Hackborn                    false,
128782c3de338d6b4ac8280e0686b8a4b39c0e3f70fDianne Hackborn                    false }
12918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            );
13018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
131983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn    public static final OpsTemplate MESSAGING_TEMPLATE = new OpsTemplate(
132983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn            new int[] { AppOpsManager.OP_READ_SMS,
133983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_RECEIVE_SMS,
134983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_RECEIVE_EMERGECY_SMS,
135983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_RECEIVE_MMS,
136983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_RECEIVE_WAP_PUSH,
137983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_WRITE_SMS,
138983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_SEND_SMS,
139983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_READ_ICC_SMS,
140983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    AppOpsManager.OP_WRITE_ICC_SMS },
141983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn            new boolean[] { true,
142983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true,
143983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true,
144983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true,
145983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true,
146983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true,
147983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true,
148983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true,
149983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn                    true }
150983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn            );
151983378738761150d8ba649b4b1d74635881e61ecDianne Hackborn
1526e91babedac9983b10fdf2650de86386800017beDianne Hackborn    public static final OpsTemplate MEDIA_TEMPLATE = new OpsTemplate(
153df3f6d6c4722a7acc8189e47d0499aaf618969f9Daniel Sandler            new int[] { AppOpsManager.OP_VIBRATE,
1547ff56d331e1dfe133e734a36d191fc1d81b31e95Dianne Hackborn                    AppOpsManager.OP_CAMERA,
1557ff56d331e1dfe133e734a36d191fc1d81b31e95Dianne Hackborn                    AppOpsManager.OP_RECORD_AUDIO,
1566e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_PLAY_AUDIO,
1576e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_TAKE_MEDIA_BUTTONS,
1586e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_TAKE_AUDIO_FOCUS,
1596e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_AUDIO_MASTER_VOLUME,
1606e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_AUDIO_VOICE_VOLUME,
1616e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_AUDIO_RING_VOLUME,
1626e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_AUDIO_MEDIA_VOLUME,
1636e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_AUDIO_ALARM_VOLUME,
1646e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_AUDIO_NOTIFICATION_VOLUME,
1656e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_AUDIO_BLUETOOTH_VOLUME, },
16627daaab633a80be50863e6539e947db674090662Dianne Hackborn            new boolean[] { false,
167d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                    true,
1687ff56d331e1dfe133e734a36d191fc1d81b31e95Dianne Hackborn                    true,
1696e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1706e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1716e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1726e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1736e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1746e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1756e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1766e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1776e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false,
1786e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    false }
1796e91babedac9983b10fdf2650de86386800017beDianne Hackborn            );
1806e91babedac9983b10fdf2650de86386800017beDianne Hackborn
1816e91babedac9983b10fdf2650de86386800017beDianne Hackborn    public static final OpsTemplate DEVICE_TEMPLATE = new OpsTemplate(
1826e91babedac9983b10fdf2650de86386800017beDianne Hackborn            new int[] { AppOpsManager.OP_POST_NOTIFICATION,
1836e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_ACCESS_NOTIFICATIONS,
1846e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_CALL_PHONE,
1856e91babedac9983b10fdf2650de86386800017beDianne Hackborn                    AppOpsManager.OP_WRITE_SETTINGS,
186ec74da60cda5d0d7d1901e20a5a7806ef4cf387fDianne Hackborn                    AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
187ec74da60cda5d0d7d1901e20a5a7806ef4cf387fDianne Hackborn                    AppOpsManager.OP_WAKE_LOCK },
1886e91babedac9983b10fdf2650de86386800017beDianne Hackborn            new boolean[] { false,
1897ff56d331e1dfe133e734a36d191fc1d81b31e95Dianne Hackborn                    true,
1907ff56d331e1dfe133e734a36d191fc1d81b31e95Dianne Hackborn                    true,
1917ff56d331e1dfe133e734a36d191fc1d81b31e95Dianne Hackborn                    true,
192ec74da60cda5d0d7d1901e20a5a7806ef4cf387fDianne Hackborn                    true,
193ec74da60cda5d0d7d1901e20a5a7806ef4cf387fDianne Hackborn                    true,  }
19418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            );
19518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
1960dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    public static final OpsTemplate[] ALL_TEMPLATES = new OpsTemplate[] {
1976e91babedac9983b10fdf2650de86386800017beDianne Hackborn            LOCATION_TEMPLATE, PERSONAL_TEMPLATE, MESSAGING_TEMPLATE,
1986e91babedac9983b10fdf2650de86386800017beDianne Hackborn            MEDIA_TEMPLATE, DEVICE_TEMPLATE
1990dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    };
2000dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
20118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    /**
20218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn     * This class holds the per-item data in our Loader.
20318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn     */
20418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public static class AppEntry {
20518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private final AppOpsState mState;
20618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private final ApplicationInfo mInfo;
20718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private final File mApkFile;
2080dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        private final SparseArray<AppOpsManager.OpEntry> mOps
2090dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                = new SparseArray<AppOpsManager.OpEntry>();
21027daaab633a80be50863e6539e947db674090662Dianne Hackborn        private final SparseArray<AppOpEntry> mOpSwitches
21127daaab633a80be50863e6539e947db674090662Dianne Hackborn                = new SparseArray<AppOpEntry>();
21218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private String mLabel;
21318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private Drawable mIcon;
21418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private boolean mMounted;
21518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
21618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public AppEntry(AppOpsState state, ApplicationInfo info) {
21718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            mState = state;
21818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            mInfo = info;
21918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            mApkFile = new File(info.sourceDir);
22018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
22118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
22227daaab633a80be50863e6539e947db674090662Dianne Hackborn        public void addOp(AppOpEntry entry, AppOpsManager.OpEntry op) {
2230dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            mOps.put(op.getOp(), op);
22427daaab633a80be50863e6539e947db674090662Dianne Hackborn            mOpSwitches.put(AppOpsManager.opToSwitch(op.getOp()), entry);
2250dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
2260dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
2270dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        public boolean hasOp(int op) {
2280dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            return mOps.indexOfKey(op) >= 0;
2290dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
2300dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
23127daaab633a80be50863e6539e947db674090662Dianne Hackborn        public AppOpEntry getOpSwitch(int op) {
23227daaab633a80be50863e6539e947db674090662Dianne Hackborn            return mOpSwitches.get(AppOpsManager.opToSwitch(op));
23327daaab633a80be50863e6539e947db674090662Dianne Hackborn        }
23427daaab633a80be50863e6539e947db674090662Dianne Hackborn
23518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public ApplicationInfo getApplicationInfo() {
23618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mInfo;
23718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
23818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
23918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public String getLabel() {
24018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mLabel;
24118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
24218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
24318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public Drawable getIcon() {
24418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            if (mIcon == null) {
24518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                if (mApkFile.exists()) {
24618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mIcon = mInfo.loadIcon(mState.mPm);
24718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    return mIcon;
24818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                } else {
24918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mMounted = false;
25018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
25118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            } else if (!mMounted) {
25218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                // If the app wasn't mounted but is now mounted, reload
25318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                // its icon.
25418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                if (mApkFile.exists()) {
25518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mMounted = true;
25618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mIcon = mInfo.loadIcon(mState.mPm);
25718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    return mIcon;
25818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
25918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            } else {
26018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return mIcon;
26118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
26218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
26318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mState.mContext.getResources().getDrawable(
26418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    android.R.drawable.sym_def_app_icon);
26518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
26618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
26718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        @Override public String toString() {
26818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mLabel;
26918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
27018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
27118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        void loadLabel(Context context) {
27218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            if (mLabel == null || !mMounted) {
27318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                if (!mApkFile.exists()) {
27418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mMounted = false;
27518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mLabel = mInfo.packageName;
27618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                } else {
27718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mMounted = true;
27818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    CharSequence label = mInfo.loadLabel(context.getPackageManager());
27918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    mLabel = label != null ? label.toString() : mInfo.packageName;
28018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
28118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
28218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
28318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    }
28418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
28518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    /**
28618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn     * This class holds the per-item data in our Loader.
28718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn     */
28818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public static class AppOpEntry {
28918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private final AppOpsManager.PackageOps mPkgOps;
29018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private final ArrayList<AppOpsManager.OpEntry> mOps
29118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                = new ArrayList<AppOpsManager.OpEntry>();
2928b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        private final ArrayList<AppOpsManager.OpEntry> mSwitchOps
29327daaab633a80be50863e6539e947db674090662Dianne Hackborn                = new ArrayList<AppOpsManager.OpEntry>();
29418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private final AppEntry mApp;
295d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn        private final int mSwitchOrder;
29618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
297d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn        public AppOpEntry(AppOpsManager.PackageOps pkg, AppOpsManager.OpEntry op, AppEntry app,
298d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                int switchOrder) {
29918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            mPkgOps = pkg;
30018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            mApp = app;
301d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn            mSwitchOrder = switchOrder;
30227daaab633a80be50863e6539e947db674090662Dianne Hackborn            mApp.addOp(this, op);
3030dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            mOps.add(op);
3048b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn            mSwitchOps.add(op);
30518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
30618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
30727daaab633a80be50863e6539e947db674090662Dianne Hackborn        private static void addOp(ArrayList<AppOpsManager.OpEntry> list, AppOpsManager.OpEntry op) {
30827daaab633a80be50863e6539e947db674090662Dianne Hackborn            for (int i=0; i<list.size(); i++) {
30927daaab633a80be50863e6539e947db674090662Dianne Hackborn                AppOpsManager.OpEntry pos = list.get(i);
31018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                if (pos.isRunning() != op.isRunning()) {
31118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    if (op.isRunning()) {
31227daaab633a80be50863e6539e947db674090662Dianne Hackborn                        list.add(i, op);
31318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                        return;
31418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    }
3150dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    continue;
31618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
3170dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                if (pos.getTime() < op.getTime()) {
31827daaab633a80be50863e6539e947db674090662Dianne Hackborn                    list.add(i, op);
31918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    return;
32018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
32118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
32227daaab633a80be50863e6539e947db674090662Dianne Hackborn            list.add(op);
32327daaab633a80be50863e6539e947db674090662Dianne Hackborn        }
32427daaab633a80be50863e6539e947db674090662Dianne Hackborn
3258b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        public void addOp(AppOpsManager.OpEntry op) {
32627daaab633a80be50863e6539e947db674090662Dianne Hackborn            mApp.addOp(this, op);
32727daaab633a80be50863e6539e947db674090662Dianne Hackborn            addOp(mOps, op);
3288b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn            if (mApp.getOpSwitch(AppOpsManager.opToSwitch(op.getOp())) == null) {
3298b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                addOp(mSwitchOps, op);
33027daaab633a80be50863e6539e947db674090662Dianne Hackborn            }
33118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
33218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
33318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public AppEntry getAppEntry() {
33418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mApp;
33518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
33618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
337d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn        public int getSwitchOrder() {
338d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn            return mSwitchOrder;
339d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn        }
340d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn
34118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public AppOpsManager.PackageOps getPackageOps() {
34218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mPkgOps;
34318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
34418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
34518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public int getNumOpEntry() {
34618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mOps.size();
34718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
34818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
34918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public AppOpsManager.OpEntry getOpEntry(int pos) {
35018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mOps.get(pos);
35118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
35218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
3538b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        private CharSequence getCombinedText(ArrayList<AppOpsManager.OpEntry> ops,
3548b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                CharSequence[] items) {
35527daaab633a80be50863e6539e947db674090662Dianne Hackborn            if (ops.size() == 1) {
3568b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                return items[ops.get(0).getOp()];
35718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            } else {
35818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                StringBuilder builder = new StringBuilder();
35927daaab633a80be50863e6539e947db674090662Dianne Hackborn                for (int i=0; i<ops.size(); i++) {
36018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    if (i > 0) {
36118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                        builder.append(", ");
36218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    }
3638b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                    builder.append(items[ops.get(i).getOp()]);
36418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
36518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return builder.toString();
36618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
36718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
36818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
3698b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        public CharSequence getSummaryText(AppOpsState state) {
3708b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn            return getCombinedText(mOps, state.mOpSummaries);
37127daaab633a80be50863e6539e947db674090662Dianne Hackborn        }
37227daaab633a80be50863e6539e947db674090662Dianne Hackborn
3738b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        public CharSequence getSwitchText(AppOpsState state) {
3748b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn            if (mSwitchOps.size() > 0) {
3758b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                return getCombinedText(mSwitchOps, state.mOpLabels);
37627daaab633a80be50863e6539e947db674090662Dianne Hackborn            } else {
3778b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                return getCombinedText(mOps, state.mOpLabels);
37827daaab633a80be50863e6539e947db674090662Dianne Hackborn            }
37927daaab633a80be50863e6539e947db674090662Dianne Hackborn        }
38027daaab633a80be50863e6539e947db674090662Dianne Hackborn
3818b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn        public CharSequence getTimeText(Resources res, boolean showEmptyText) {
38218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            if (isRunning()) {
38318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return res.getText(R.string.app_ops_running);
38418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
38518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            if (getTime() > 0) {
38618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return DateUtils.getRelativeTimeSpanString(getTime(),
38718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                        System.currentTimeMillis(),
38818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                        DateUtils.MINUTE_IN_MILLIS,
38918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                        DateUtils.FORMAT_ABBREV_RELATIVE);
39018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
3918b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn            return showEmptyText ? res.getText(R.string.app_ops_never_used) : "";
39218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
39318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
39418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public boolean isRunning() {
39518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mOps.get(0).isRunning();
39618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
39718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
39818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public long getTime() {
39918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mOps.get(0).getTime();
40018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
40118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
40218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        @Override public String toString() {
40318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return mApp.getLabel();
40418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
40518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    }
40618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
40718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    /**
40818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn     * Perform alphabetical comparison of application entry objects.
40918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn     */
41018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public static final Comparator<AppOpEntry> APP_OP_COMPARATOR = new Comparator<AppOpEntry>() {
41118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        private final Collator sCollator = Collator.getInstance();
41218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        @Override
41318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        public int compare(AppOpEntry object1, AppOpEntry object2) {
414d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn            if (object1.getSwitchOrder() != object2.getSwitchOrder()) {
415d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                return object1.getSwitchOrder() < object2.getSwitchOrder() ? -1 : 1;
416d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn            }
41718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            if (object1.isRunning() != object2.isRunning()) {
41818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                // Currently running ops go first.
41918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return object1.isRunning() ? -1 : 1;
42018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
42118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            if (object1.getTime() != object2.getTime()) {
42218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                // More recent times go first.
42318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                return object1.getTime() > object2.getTime() ? -1 : 1;
42418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
42518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            return sCollator.compare(object1.getAppEntry().getLabel(),
42618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    object2.getAppEntry().getLabel());
42718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
42818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    };
42918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
43018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    private void addOp(List<AppOpEntry> entries, AppOpsManager.PackageOps pkgOps,
431d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn            AppEntry appEntry, AppOpsManager.OpEntry opEntry, boolean allowMerge, int switchOrder) {
43227daaab633a80be50863e6539e947db674090662Dianne Hackborn        if (allowMerge && entries.size() > 0) {
43318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            AppOpEntry last = entries.get(entries.size()-1);
43418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            if (last.getAppEntry() == appEntry) {
43518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                boolean lastExe = last.getTime() != 0;
43618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                boolean entryExe = opEntry.getTime() != 0;
43718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                if (lastExe == entryExe) {
4380dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package "
4390dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                            + pkgOps.getPackageName() + ": append to " + last);
4408b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn                    last.addOp(opEntry);
44118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    return;
44218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
44318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
44418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
44527daaab633a80be50863e6539e947db674090662Dianne Hackborn        AppOpEntry entry = appEntry.getOpSwitch(opEntry.getOp());
44627daaab633a80be50863e6539e947db674090662Dianne Hackborn        if (entry != null) {
4478b0afc7fb53b90e522b86ba04bb17c0cba2364abDianne Hackborn            entry.addOp(opEntry);
44827daaab633a80be50863e6539e947db674090662Dianne Hackborn            return;
44927daaab633a80be50863e6539e947db674090662Dianne Hackborn        }
450d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn        entry = new AppOpEntry(pkgOps, opEntry, appEntry, switchOrder);
4510dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (DEBUG) Log.d(TAG, "Add op " + opEntry.getOp() + " to package "
4520dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                + pkgOps.getPackageName() + ": making new " + entry);
45318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        entries.add(entry);
45418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    }
45518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
45618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public List<AppOpEntry> buildState(OpsTemplate tpl) {
45718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        return buildState(tpl, 0, null);
45818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    }
45918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
4600dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    private AppEntry getAppEntry(final Context context, final HashMap<String, AppEntry> appEntries,
4610dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            final String packageName, ApplicationInfo appInfo) {
4620dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        AppEntry appEntry = appEntries.get(packageName);
4630dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (appEntry == null) {
4640dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            if (appInfo == null) {
4650dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                try {
4660dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    appInfo = mPm.getApplicationInfo(packageName,
4670dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                            PackageManager.GET_DISABLED_COMPONENTS
4680dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                            | PackageManager.GET_UNINSTALLED_PACKAGES);
4690dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                } catch (PackageManager.NameNotFoundException e) {
4700dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    Log.w(TAG, "Unable to find info for package " + packageName);
4710dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    return null;
4720dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                }
4730dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            }
4740dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            appEntry = new AppEntry(this, appInfo);
4750dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            appEntry.loadLabel(context);
4760dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            appEntries.put(packageName, appEntry);
4770dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
4780dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        return appEntry;
4790dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn    }
4800dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
48118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    public List<AppOpEntry> buildState(OpsTemplate tpl, int uid, String packageName) {
48218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        final Context context = mContext;
48318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
48418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        final HashMap<String, AppEntry> appEntries = new HashMap<String, AppEntry>();
48527daaab633a80be50863e6539e947db674090662Dianne Hackborn        final List<AppOpEntry> entries = new ArrayList<AppOpEntry>();
4860dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
48727daaab633a80be50863e6539e947db674090662Dianne Hackborn        final ArrayList<String> perms = new ArrayList<String>();
48827daaab633a80be50863e6539e947db674090662Dianne Hackborn        final ArrayList<Integer> permOps = new ArrayList<Integer>();
489d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn        final int[] opToOrder = new int[AppOpsManager._NUM_OP];
4900dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        for (int i=0; i<tpl.ops.length; i++) {
49127daaab633a80be50863e6539e947db674090662Dianne Hackborn            if (tpl.showPerms[i]) {
49227daaab633a80be50863e6539e947db674090662Dianne Hackborn                String perm = AppOpsManager.opToPermission(tpl.ops[i]);
49327daaab633a80be50863e6539e947db674090662Dianne Hackborn                if (perm != null && !perms.contains(perm)) {
49427daaab633a80be50863e6539e947db674090662Dianne Hackborn                    perms.add(perm);
49527daaab633a80be50863e6539e947db674090662Dianne Hackborn                    permOps.add(tpl.ops[i]);
496d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                    opToOrder[tpl.ops[i]] = i;
49727daaab633a80be50863e6539e947db674090662Dianne Hackborn                }
4980dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            }
4990dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
50018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
50118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        List<AppOpsManager.PackageOps> pkgs;
50218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        if (packageName != null) {
50318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            pkgs = mAppOps.getOpsForPackage(uid, packageName, tpl.ops);
50418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        } else {
50518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            pkgs = mAppOps.getPackagesForOps(tpl.ops);
50618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
5070dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn
5080dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (pkgs != null) {
5090dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            for (int i=0; i<pkgs.size(); i++) {
5100dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                AppOpsManager.PackageOps pkgOps = pkgs.get(i);
5110dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                AppEntry appEntry = getAppEntry(context, appEntries, pkgOps.getPackageName(), null);
5120dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                if (appEntry == null) {
5130dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    continue;
5140dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                }
5150dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                for (int j=0; j<pkgOps.getOps().size(); j++) {
5160dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    AppOpsManager.OpEntry opEntry = pkgOps.getOps().get(j);
517d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                    addOp(entries, pkgOps, appEntry, opEntry, packageName == null,
518d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                            packageName == null ? 0 : opToOrder[opEntry.getOp()]);
51918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                }
52018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
52118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
52218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
5230dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        List<PackageInfo> apps;
5240dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        if (packageName != null) {
5250dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            apps = new ArrayList<PackageInfo>();
5260dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            try {
5270dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                PackageInfo pi = mPm.getPackageInfo(packageName, PackageManager.GET_PERMISSIONS);
5280dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                apps.add(pi);
5290dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            } catch (NameNotFoundException e) {
53018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
5310dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        } else {
5320dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            String[] permsArray = new String[perms.size()];
5330dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            perms.toArray(permsArray);
5340dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            apps = mPm.getPackagesHoldingPermissions(permsArray, 0);
5350dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        }
5360dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn        for (int i=0; i<apps.size(); i++) {
5370dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            PackageInfo appInfo = apps.get(i);
5380dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            AppEntry appEntry = getAppEntry(context, appEntries, appInfo.packageName,
5390dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    appInfo.applicationInfo);
5400dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            if (appEntry == null) {
5410dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                continue;
5420dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            }
5430dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            List<AppOpsManager.OpEntry> dummyOps = null;
5440dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn            AppOpsManager.PackageOps pkgOps = null;
5457d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler            if (appInfo.requestedPermissions != null) {
5467d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                for (int j=0; j<appInfo.requestedPermissions.length; j++) {
5477d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                    if (appInfo.requestedPermissionsFlags != null) {
5487d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        if ((appInfo.requestedPermissionsFlags[j]
5497d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                                & PackageInfo.REQUESTED_PERMISSION_GRANTED) == 0) {
5507d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                            if (DEBUG) Log.d(TAG, "Pkg " + appInfo.packageName + " perm "
5517d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                                    + appInfo.requestedPermissions[j] + " not granted; skipping");
5527d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                            break;
5537d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        }
55418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn                    }
5557d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                    if (DEBUG) Log.d(TAG, "Pkg " + appInfo.packageName + ": requested perm "
5567d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                            + appInfo.requestedPermissions[j]);
5577d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                    for (int k=0; k<perms.size(); k++) {
5587d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        if (!perms.get(k).equals(appInfo.requestedPermissions[j])) {
5597d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                            continue;
5607d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        }
5617d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        if (DEBUG) Log.d(TAG, "Pkg " + appInfo.packageName + " perm " + perms.get(k)
5627d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                                + " has op " + permOps.get(k) + ": " + appEntry.hasOp(permOps.get(k)));
5637d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        if (appEntry.hasOp(permOps.get(k))) {
5647d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                            continue;
5657d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        }
5667d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        if (dummyOps == null) {
5677d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                            dummyOps = new ArrayList<AppOpsManager.OpEntry>();
5687d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                            pkgOps = new AppOpsManager.PackageOps(
5697d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                                    appInfo.packageName, appInfo.applicationInfo.uid, dummyOps);
5707d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler
5717d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        }
5727d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        AppOpsManager.OpEntry opEntry = new AppOpsManager.OpEntry(
5737d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                                permOps.get(k), AppOpsManager.MODE_ALLOWED, 0, 0, 0);
5747d3a4c160cac37b72aa9149952358df4a3912cfbDaniel Sandler                        dummyOps.add(opEntry);
575d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                        addOp(entries, pkgOps, appEntry, opEntry, packageName == null,
576d69e8dc44173c33c5425158c027bfe44ddcacf85Dianne Hackborn                                packageName == null ? 0 : opToOrder[opEntry.getOp()]);
5770dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                    }
5780dd9902c89e7b705fd73158aadf1bf27843ad201Dianne Hackborn                }
57918b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn            }
58018b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        }
58118b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
58218b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        // Sort the list.
58318b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        Collections.sort(entries, APP_OP_COMPARATOR);
58418b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn
58518b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        // Done!
58618b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn        return entries;
58718b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn    }
58818b64f446cd7b9043909b0cd42d1ab364392da24Dianne Hackborn}
589