1/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.settings.applications;
17
18import static android.net.NetworkPolicyManager.POLICY_NONE;
19import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
20
21import android.app.ActivityManager;
22import android.app.AlertDialog;
23import android.app.AppOpsManager;
24import android.app.INotificationManager;
25import android.content.Context;
26import android.content.DialogInterface;
27import android.content.pm.ApplicationInfo;
28import android.content.pm.IPackageManager;
29import android.content.pm.PackageManager;
30import android.net.NetworkPolicyManager;
31import android.os.AsyncTask;
32import android.os.Bundle;
33import android.os.RemoteException;
34import android.os.ServiceManager;
35import android.os.UserHandle;
36import android.webkit.IWebViewUpdateService;
37
38import com.android.settings.R;
39
40import java.util.List;
41
42public class ResetAppsHelper implements DialogInterface.OnClickListener,
43        DialogInterface.OnDismissListener {
44
45    private static final String EXTRA_RESET_DIALOG = "resetDialog";
46
47    private final PackageManager mPm;
48    private final IPackageManager mIPm;
49    private final INotificationManager mNm;
50    private final IWebViewUpdateService mWvus;
51    private final NetworkPolicyManager mNpm;
52    private final AppOpsManager mAom;
53    private final Context mContext;
54
55    private AlertDialog mResetDialog;
56
57    public ResetAppsHelper(Context context) {
58        mContext = context;
59        mPm = context.getPackageManager();
60        mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
61        mNm = INotificationManager.Stub.asInterface(
62                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
63        mWvus = IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
64        mNpm = NetworkPolicyManager.from(context);
65        mAom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
66    }
67
68    public void onRestoreInstanceState(Bundle savedInstanceState) {
69        if (savedInstanceState != null && savedInstanceState.getBoolean(EXTRA_RESET_DIALOG)) {
70            buildResetDialog();
71        }
72    }
73
74    public void onSaveInstanceState(Bundle outState) {
75        if (mResetDialog != null) {
76            outState.putBoolean(EXTRA_RESET_DIALOG, true);
77        }
78    }
79
80    public void stop() {
81        if (mResetDialog != null) {
82            mResetDialog.dismiss();
83            mResetDialog = null;
84        }
85    }
86
87    void buildResetDialog() {
88        if (mResetDialog == null) {
89            mResetDialog = new AlertDialog.Builder(mContext)
90                    .setTitle(R.string.reset_app_preferences_title)
91                    .setMessage(R.string.reset_app_preferences_desc)
92                    .setPositiveButton(R.string.reset_app_preferences_button, this)
93                    .setNegativeButton(R.string.cancel, null)
94                    .setOnDismissListener(this)
95                    .show();
96        }
97    }
98
99    @Override
100    public void onDismiss(DialogInterface dialog) {
101        if (mResetDialog == dialog) {
102            mResetDialog = null;
103        }
104    }
105
106    @Override
107    public void onClick(DialogInterface dialog, int which) {
108        if (mResetDialog != dialog) {
109            return;
110        }
111        AsyncTask.execute(new Runnable() {
112            @Override
113            public void run() {
114                List<ApplicationInfo> apps = mPm.getInstalledApplications(
115                        PackageManager.GET_DISABLED_COMPONENTS);
116                for (int i = 0; i < apps.size(); i++) {
117                    ApplicationInfo app = apps.get(i);
118                    try {
119                        mNm.setNotificationsEnabledForPackage(app.packageName, app.uid, true);
120                    } catch (android.os.RemoteException ex) {
121                    }
122                    if (!app.enabled) {
123                        if (mPm.getApplicationEnabledSetting(app.packageName)
124                                == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
125                                && !isNonEnableableFallback(app.packageName)) {
126                            mPm.setApplicationEnabledSetting(app.packageName,
127                                    PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
128                                    PackageManager.DONT_KILL_APP);
129                        }
130                    }
131                }
132                try {
133                    mIPm.resetApplicationPreferences(UserHandle.myUserId());
134                } catch (RemoteException e) {
135                }
136                mAom.resetAllModes();
137                final int[] restrictedUids = mNpm.getUidsWithPolicy(
138                        POLICY_REJECT_METERED_BACKGROUND);
139                final int currentUserId = ActivityManager.getCurrentUser();
140                for (int uid : restrictedUids) {
141                    // Only reset for current user
142                    if (UserHandle.getUserId(uid) == currentUserId) {
143                        mNpm.setUidPolicy(uid, POLICY_NONE);
144                    }
145                }
146            }
147        });
148    }
149
150    private boolean isNonEnableableFallback(String packageName) {
151        try {
152            return mWvus.isFallbackPackage(packageName);
153        } catch (RemoteException e) {
154            throw new RuntimeException(e);
155        }
156    }
157}
158