1 /*
2  * Copyright (C) 2012 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  */
16 
17 package com.android.onetimeinitializer;
18 
19 import android.content.ComponentName;
20 import android.content.ContentResolver;
21 import android.content.ContentValues;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.SharedPreferences;
25 import android.database.Cursor;
26 import android.net.Uri;
27 import android.util.Log;
28 
29 import java.net.URISyntaxException;
30 import java.util.Set;
31 
32 /**
33  * A class that performs one-time initialization after installation.
34  *
35  * <p>Android doesn't offer any mechanism to trigger an app right after installation, so we use the
36  * BOOT_COMPLETED broadcast intent instead.  This means, when the app is upgraded, the
37  * initialization code here won't run until the device reboots.
38  */
39 public class OneTimeInitializer {
40     private static final String TAG = OneTimeInitializer.class.getSimpleName();
41 
42     // Name of the shared preferences file.
43     private static final String SHARED_PREFS_FILE = "oti";
44 
45     // Name of the preference containing the mapping version.
46     private static final String MAPPING_VERSION_PREF = "mapping_version";
47 
48     // This is the content uri for Launcher content provider. See
49     // LauncherSettings and LauncherProvider in the Launcher app for details.
50     private static final Uri LAUNCHER_CONTENT_URI =
51             Uri.parse("content://com.android.launcher2.settings/favorites?notify=true");
52 
53     private static final String LAUNCHER_ID_COLUMN = "_id";
54     private static final String LAUNCHER_INTENT_COLUMN = "intent";
55 
56     private SharedPreferences mPreferences;
57     private Context mContext;
58 
OneTimeInitializer(Context context)59     OneTimeInitializer(Context context) {
60         mContext = context;
61         mPreferences = mContext.getSharedPreferences(SHARED_PREFS_FILE, Context.MODE_PRIVATE);
62     }
63 
initialize()64     void initialize() {
65         if (Log.isLoggable(TAG, Log.VERBOSE)) {
66             Log.v(TAG, "OneTimeInitializer.initialize");
67         }
68 
69         final int currentVersion = getMappingVersion();
70         int newVersion = currentVersion;
71         if (currentVersion < 1) {
72             if (Log.isLoggable(TAG, Log.INFO)) {
73                 Log.i(TAG, "Updating to version 1.");
74             }
75             updateDialtactsLauncher();
76 
77             newVersion = 1;
78         }
79 
80         updateMappingVersion(newVersion);
81     }
82 
getMappingVersion()83     private int getMappingVersion() {
84         return mPreferences.getInt(MAPPING_VERSION_PREF, 0);
85     }
86 
updateMappingVersion(int version)87     private void updateMappingVersion(int version) {
88         SharedPreferences.Editor ed = mPreferences.edit();
89         ed.putInt(MAPPING_VERSION_PREF, version);
90         ed.commit();
91     }
92 
updateDialtactsLauncher()93     private void updateDialtactsLauncher() {
94         ContentResolver cr = mContext.getContentResolver();
95         Cursor c = cr.query(LAUNCHER_CONTENT_URI,
96                 new String[]{LAUNCHER_ID_COLUMN, LAUNCHER_INTENT_COLUMN}, null, null, null);
97         if (c == null) {
98             return;
99         }
100 
101         try {
102             if (Log.isLoggable(TAG, Log.DEBUG)) {
103                 Log.d(TAG, "Total launcher icons: " + c.getCount());
104             }
105 
106             while (c.moveToNext()) {
107                 long favoriteId = c.getLong(0);
108                 final String intentUri = c.getString(1);
109                 if (intentUri != null) {
110                     try {
111                         final Intent intent = Intent.parseUri(intentUri, 0);
112                         final ComponentName componentName = intent.getComponent();
113                         final Set<String> categories = intent.getCategories();
114                         if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
115                                 componentName != null &&
116                                 "com.android.contacts".equals(componentName.getPackageName()) &&
117                                 "com.android.contacts.activities.DialtactsActivity".equals(
118                                         componentName.getClassName()) &&
119                                 categories != null &&
120                                 categories.contains(Intent.CATEGORY_LAUNCHER)) {
121 
122                             final ComponentName newName = new ComponentName("com.android.dialer",
123                                     "com.android.dialer.DialtactsActivity");
124                             intent.setComponent(newName);
125                             final ContentValues values = new ContentValues();
126                             values.put(LAUNCHER_INTENT_COLUMN, intent.toUri(0));
127 
128                             String updateWhere = LAUNCHER_ID_COLUMN + "=" + favoriteId;
129                             cr.update(LAUNCHER_CONTENT_URI, values, updateWhere, null);
130                             if (Log.isLoggable(TAG, Log.INFO)) {
131                                 Log.i(TAG, "Updated " + componentName + " to " + newName);
132                             }
133                         }
134                     } catch (RuntimeException ex) {
135                         Log.e(TAG, "Problem moving Dialtacts activity", ex);
136                     } catch (URISyntaxException e) {
137                         Log.e(TAG, "Problem moving Dialtacts activity", e);
138                     }
139                 }
140             }
141 
142         } finally {
143             if (c != null) {
144                 c.close();
145             }
146         }
147     }
148 }
149