SnapdragonLauncher: Switch solution between Launcher3 and Flat Launcher

Description:
1、Switch solution between Launcher3 and Flat Launcher

Change-Id: I996db527935ae79f5058d0bfc216dbfa979ba636
CRs-Fixed: 1081856
diff --git a/Android.mk b/Android.mk
index b1aa7d8..91d5b35 100644
--- a/Android.mk
+++ b/Android.mk
@@ -48,7 +48,7 @@
 LOCAL_SDK_VERSION := current
 LOCAL_PACKAGE_NAME := SnapdragonLauncher
 LOCAL_PRIVILEGED_MODULE := true
-LOCAL_CERTIFICATE := shared
+LOCAL_CERTIFICATE := platform
 
 LOCAL_OVERRIDES_PACKAGES := Home Launcher2
 
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 8962b57..0d71cce 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -20,6 +20,7 @@
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
     package="org.codeaurora.snaplauncher">
+
     <uses-sdk android:targetSdkVersion="23" android:minSdkVersion="16"/>
 
     <permission
@@ -62,12 +63,14 @@
     <uses-permission android:name="com.android.launcher3.permission.WRITE_SETTINGS" />
     <uses-permission android:name="com.android.launcher3.permission.RECEIVE_LAUNCH_BROADCASTS" />
     <uses-permission android:name="com.android.launcher3.permission.RECEIVE_FIRST_LOAD_BROADCAST" />
+    <uses-permission android:name="android.permission.SET_PREFERRED_APPLICATIONS"/>
+    <uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>
 
     <application
         android:allowBackup="@bool/enable_backup"
         android:backupAgent="com.android.launcher3.LauncherBackupAgentHelper"
         android:hardwareAccelerated="true"
-        android:icon="@mipmap/ic_launcher_home"
+        android:icon="@mipmap/ic_flat_launcher"
         android:label="@string/snaplauncher_app_name"
         android:largeHeap="@bool/config_largeHeap"
         android:restoreAnyVersion="true"
@@ -112,6 +115,28 @@
         </activity>
 
         -->
+        <activity
+            android:name="org.codeaurora.snaplauncher.SwitchToLauncher3Activity"
+            android:label="@string/switch_to_launcher3"
+            android:enabled="false"
+            android:exported="false"
+            android:theme="@style/Theme.UserDialog">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
+
+        <activity
+            android:name="org.codeaurora.snaplauncher.SwitchToFlatLauncherActivity"
+            android:label="@string/snaplauncher_app_name"
+            android:enabled="true"
+            android:theme="@style/Theme.UserDialog">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+        </activity>
 
         <activity
             android:name="com.android.launcher3.ToggleWeightWatcher"
diff --git a/res/mipmap-hdpi/ic_flat_launcher.png b/res/mipmap-hdpi/ic_flat_launcher.png
new file mode 100644
index 0000000..1f34ae0
--- /dev/null
+++ b/res/mipmap-hdpi/ic_flat_launcher.png
Binary files differ
diff --git a/res/mipmap-hdpi/ic_launcher3.png b/res/mipmap-hdpi/ic_launcher3.png
new file mode 100644
index 0000000..9bbe7c2
--- /dev/null
+++ b/res/mipmap-hdpi/ic_launcher3.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_flat_launcher.png b/res/mipmap-mdpi/ic_flat_launcher.png
new file mode 100644
index 0000000..66adf64
--- /dev/null
+++ b/res/mipmap-mdpi/ic_flat_launcher.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher3.png b/res/mipmap-mdpi/ic_launcher3.png
new file mode 100644
index 0000000..f50aa3b
--- /dev/null
+++ b/res/mipmap-mdpi/ic_launcher3.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_flat_launcher.png b/res/mipmap-xhdpi/ic_flat_launcher.png
new file mode 100644
index 0000000..64d19cc
--- /dev/null
+++ b/res/mipmap-xhdpi/ic_flat_launcher.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher3.png b/res/mipmap-xhdpi/ic_launcher3.png
new file mode 100644
index 0000000..da9f714
--- /dev/null
+++ b/res/mipmap-xhdpi/ic_launcher3.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_flat_launcher.png b/res/mipmap-xxhdpi/ic_flat_launcher.png
new file mode 100644
index 0000000..6d2c31f
--- /dev/null
+++ b/res/mipmap-xxhdpi/ic_flat_launcher.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher3.png b/res/mipmap-xxhdpi/ic_launcher3.png
new file mode 100644
index 0000000..c6b7637
--- /dev/null
+++ b/res/mipmap-xxhdpi/ic_launcher3.png
Binary files differ
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 0076c66..ac40bb6 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -107,4 +107,14 @@
         <item name="android:layout_gravity">top|right</item>
     </style>
 
+    <style name="Theme.UserDialog" parent="@style/BaseWallpaperTheme">
+        <item name="android:windowFrame">@null</item>
+        <item name="android:windowIsFloating">true</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowNoTitle">true</item>
+        <item name="android:windowShowWallpaper">false</item>
+        <item name="android:background">@android:color/transparent</item>
+        <item name="android:windowBackground">@android:color/transparent</item>
+    </style>
+
 </resources>
diff --git a/res/xml/custom_workspace_4x4.xml b/res/xml/custom_workspace_4x4.xml
index 4b87a8c..ca6bc5a 100644
--- a/res/xml/custom_workspace_4x4.xml
+++ b/res/xml/custom_workspace_4x4.xml
@@ -74,144 +74,6 @@
     </resolve>
 
     <!-- Workspace screen 1 -->
-    <folder
-        launcher:screen="0"
-        launcher:x="0"
-        launcher:y="2"
-        launcher:title="@string/qualcomm_apps_folder_name">
-        <favorite
-            launcher:packageName="com.qualcomm.adrenotest"
-            launcher:className="android.app.NativeActivity"/>
-        <favorite
-            launcher:packageName="com.qti.antitheftdemo"
-            launcher:className="com.qti.antitheftdemo.MainActivity" />
-        <favorite
-            launcher:packageName="com.android.audiosettings"
-            launcher:className="com.android.audiosettings.AudioSettings" />
-        <favorite
-            launcher:packageName="com.android.qlogging"
-            launcher:className="com.android.qlogging.Main"/>
-        <favorite
-            launcher:packageName="org.codeaurora.bluetooth.bttestapp"
-            launcher:className="org.codeaurora.bluetooth.bttestapp.MainActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.carrierconfigure"
-            launcher:className="com.qualcomm.qti.carrierconfigure.ConfigurationActivity" />
-        <favorite
-            launcher:packageName="com.quicinc.cne.settings"
-            launcher:className="com.quicinc.cne.settings.CneSettings"/>
-        <favorite
-            launcher:packageName="com.qti.csk"
-            launcher:className="com.qti.csk.MainActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.embmstest"
-            launcher:className="com.qualcomm.embmstest.EmbmsTestAppActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.auth.fidocryptosample"
-            launcher:className="com.qualcomm.qti.auth.fidocryptosample.FidoCryptoClientActivity"/>
-        <favorite
-            launcher:packageName="org.codeaurora.bluetooth.hidtestapp"
-            launcher:className="org.codeaurora.bluetooth.hidtestapp.HidTestApp" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.improvetouch"
-            launcher:className="com.qualcomm.qti.socketservice.MainActivity" />
-        <shortcut
-            launcher:uri="#Intent;action=android.intent.action.MAIN;component=org.codeaurora.snaplauncher/org.codeaurora.snaplauncher.SwitchToLauncher3Activity;end"
-            launcher:icon="@mipmap/ic_launcher_home"
-            launcher:title="@string/switch_to_launcher3"/>
-        <favorite
-            launcher:packageName="com.qualcomm.qti.ltedirectdiscoverytest"
-            launcher:className="com.qualcomm.qti.ltedirectdiscoverytest.MainActivity"/>
-        <favorite
-            launcher:packageName="com.qualcomm.qti.uimlpatest"
-            launcher:className="com.qualcomm.qti.uimlpatest.LpaMainActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.securemsm.mdtp.MdtpDemo"
-            launcher:className="com.qualcomm.qti.securemsm.mdtp.MdtpDemo.MainUserActivity" />
-        <favorite
-            launcher:packageName="com.android.MultiplePdpTest"
-            launcher:className="com.android.MultiplePdpTest.ServiceTypeListActivity"/>
-        <favorite
-            launcher:packageName="com.android.nativeaudiolatency"
-            launcher:className="com.android.nativeaudiolatency.NativeAudioLatency" />
-        <favorite
-            launcher:packageName="com.qualcomm.pipcamera"
-            launcher:className="com.qualcomm.pipcamera.PIPCamera" />
-        <favorite
-            launcher:packageName="com.playready.junit"
-            launcher:className="com.playready.junit.PlayreadyJUnitTest" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.presenceapp"
-            launcher:className="com.qualcomm.qti.presenceapp.MainActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.app"
-            launcher:className="com.qualcomm.qti.app.MainActivity"/>
-        <favorite
-            launcher:packageName="com.qualcomm.qti.qlogcat"
-            launcher:className="com.qualcomm.qti.qlogcat.QLogcatActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.sensors.qsensortest"
-            launcher:className="com.qualcomm.qti.sensors.ui.qsensortest.TabControl" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.logkit"
-            launcher:className="com.qualcomm.qti.logkit.cActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.qct.dlt"
-            launcher:className="com.qualcomm.qct.dlt.MainActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.location.qvtester"
-            launcher:className="com.qualcomm.location.qvtester.InputCriteria"/>
-        <favorite
-            launcher:packageName="com.qualcomm.secureindicator"
-            launcher:className="com.qualcomm.secureindicator.MainActivity" />
-        <favorite
-            launcher:packageName="com.qti.csm"
-            launcher:className="com.qti.csm.EnterSet" />
-        <favorite
-            launcher:packageName="com.qualcomm.settings"
-            launcher:className="com.qualcomm.settings.SetScreenTimeout" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.soundtrigger"
-            launcher:className="com.qualcomm.qti.soundtrigger.ux.DetectionActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.qti.biometrics.voiceprint.voiceprintdemo"
-            launcher:className="com.qualcomm.qti.biometrics.voiceprint.voiceprintdemo.ui.MainActivity" />
-        <favorite
-            launcher:packageName="com.qualcomm.wfd.client"
-            launcher:className="com.qualcomm.wfd.client.WFDClientActivity"/>
-        <favorite
-            launcher:packageName="com.widevine.demo"
-            launcher:className="com.widevine.demo.WidevineSamplePlayer" />
-        <favorite
-            launcher:packageName="com.quicinc.wipoweragent"
-            launcher:className="com.quicinc.wipoweragent.WipowerAgentActivity" />
-    </folder>
-
-    <folder
-        launcher:screen="0"
-        launcher:x="3"
-        launcher:y="2"
-        launcher:title="@string/google_folder_name">
-        <favorite
-            launcher:packageName="com.google.android.GoogleCamera"
-            launcher:className="com.android.camera.CameraLauncher" />
-        <favorite
-            launcher:packageName="com.android.chrome"
-            launcher:className="com.google.android.apps.chrome.Main" />
-        <favorite
-            launcher:packageName="com.google.android.exoplayer.demo"
-            launcher:className="com.google.android.exoplayer.demo.SampleChooserActivity" />
-        <favorite
-            launcher:packageName="com.google.android.googlequicksearchbox"
-            launcher:className="com.google.android.googlequicksearchbox.SearchActivity" />
-        <favorite
-            launcher:packageName="com.google.android.apps.photos"
-            launcher:className="com.google.android.apps.photos.home.HomeActivity" />
-
-        <favorite
-            launcher:packageName="com.google.android.googlequicksearchbox"
-            launcher:className="com.google.android.googlequicksearchbox.VoiceSearchActivity" />
-    </folder>
 
     <resolve
         launcher:screen="0"
@@ -243,6 +105,13 @@
     </resolve>
 
     <!-- Workspace screen 2 -->
+    <shortcut
+        launcher:uri="#Intent;action=android.intent.action.MAIN;component=org.codeaurora.snaplauncher/org.codeaurora.snaplauncher.SwitchToLauncher3Activity;end"
+        launcher:icon="@mipmap/ic_launcher3"
+        launcher:title="@string/switch_to_launcher3"
+        launcher:screen="1"
+        launcher:x="0"
+        launcher:y="0"/>
     <favorite
         launcher:packageName="com.android.calendar"
         launcher:className="com.android.calendar.AllInOneActivity"
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index df2bd5e..1677933 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -1650,8 +1650,6 @@
             // Cross reference all the applications in our apps list with items in the workspace
             ArrayList<ItemInfo> tmpInfos;
             ArrayList<ItemInfo> added = new ArrayList<ItemInfo>();
-            ArrayList<ItemInfo> qualcommApps = new ArrayList<ItemInfo>();
-            ArrayList<ItemInfo> googleApps = new ArrayList<ItemInfo>();
             synchronized (sBgLock) {
                 for (AppInfo app : mBgAllAppsList.data) {
                     tmpInfos = getItemInfoForComponentName(app.componentName, app.user);
@@ -1662,13 +1660,6 @@
                         if (packageName.equals("org.codeaurora.snaplauncher")
                                 || packageName.equals("")){
                             continue;
-                        }else if (packageName.contains("com.qualcomm")
-                                ||packageName.contains("com.qti")
-                                ||packageName.contains("com.quicinc")
-                                ||packageName.contains("org.codeaurora")){
-                            qualcommApps.add(app);
-                        }else if (packageName.contains("com.google")){
-                            googleApps.add(app);
                         }else {
                             // We are missing an application icon, so add this to the workspace
                             added.add(app);
@@ -1679,54 +1670,11 @@
                 }
             }
 
-            if (!qualcommApps.isEmpty()){
-                addAndBindAddedFolderItems(qualcommApps, context.getResources()
-                        .getString(R.string.qualcomm_apps_folder_name));
-            }
-
-            if (!googleApps.isEmpty()){
-                addAndBindAddedFolderItems(googleApps,context.getResources()
-                        .getString(R.string.google_folder_name));
-            }
-
             if (!added.isEmpty()) {
                 addAndBindAddedWorkspaceItems(context, added);
             }
         }
 
-        private void addAndBindAddedFolderItems(final ArrayList<? extends ItemInfo> apps,
-                    String title){
-            final Map<FolderInfo, List<ShortcutInfo>> map = new HashMap<>();
-            synchronized(sBgLock) {
-
-                for (FolderInfo info:sBgFolders){
-                    List<ShortcutInfo> list = new ArrayList<>();
-                    for (ItemInfo item : apps) {
-                        if (info.title.equals(title)){
-                            list.add(((AppInfo) item).makeShortcut());
-                        }
-                    }
-                    if (list.size() > 0){
-                        map.put(info, list);
-                    }
-                }
-                runOnMainThread(new Runnable() {
-                    @Override
-                    public void run() {
-                        Iterator iterator = map.entrySet().iterator();
-                        while (iterator.hasNext()) {
-                            Map.Entry entry = (Map.Entry) iterator.next();
-                            FolderInfo key = (FolderInfo) entry.getKey();
-                            List<ShortcutInfo> val = (List<ShortcutInfo>)entry.getValue();
-                            for (ShortcutInfo info: val){
-                                key.add(info);
-                            }
-                        }
-                    }
-                });
-            }
-        }
-
         public void run() {
             synchronized (mLock) {
                 if (mStopped) {
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 420d675..c2bb7c3 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -18,6 +18,7 @@
 
 import android.annotation.TargetApi;
 import android.app.Activity;
+import android.app.ActivityManager;
 import android.app.SearchManager;
 import android.appwidget.AppWidgetManager;
 import android.appwidget.AppWidgetProviderInfo;
@@ -25,6 +26,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.SharedPreferences;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
@@ -61,6 +63,7 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -117,6 +120,12 @@
 
     public static final String ALLOW_ROTATION_PREFERENCE_KEY = "pref_allowRotation";
 
+    // set Flat Launcher as default launcher
+    public static final String FLAT_LAUNCHER_PACKAGENAME = "org.codeaurora.snaplauncher";
+    // set Launcher3 as default launcher
+    public static final String LAUNCHER_PACKAGENAME = "com.android.launcher3";
+    public static final String LAUNCHER_CLASSNAME = "com.android.launcher3.Launcher";
+
     public static boolean isPropertyEnabled(String propertyName) {
         return Log.isLoggable(propertyName, Log.VERBOSE);
     }
@@ -788,4 +797,85 @@
 
         return explicitIntent;
     }
+
+    public static void setupDefaultLauncher(PackageManager pm, Context context,
+            ComponentName defaultLauncher){
+        if (defaultLauncher.getPackageName().equals(getLauncherPackageName(context))){
+            return;
+        }
+        //clear default launcher
+        ArrayList<IntentFilter> intentList = new ArrayList<IntentFilter>();
+        ArrayList<ComponentName> cnList = new ArrayList<ComponentName>();
+        context.getPackageManager().getPreferredActivities(intentList, cnList, null);
+        IntentFilter dhIF;
+        for(int i = 0; i < cnList.size(); i++)
+        {
+            dhIF = intentList.get(i);
+            if(dhIF.hasAction(Intent.ACTION_MAIN) &&
+                    dhIF.hasCategory(Intent.CATEGORY_HOME))
+            {
+                context.getPackageManager().clearPackagePreferredActivities(cnList.get(i)
+                        .getPackageName());
+            }
+        }
+
+        Intent queryIntent = new Intent();
+        queryIntent.addCategory(Intent.CATEGORY_HOME);
+        queryIntent.setAction(Intent.ACTION_MAIN);
+
+        List<ResolveInfo> homeActivities = pm.queryIntentActivities(queryIntent, 0);
+        if(homeActivities == null) {
+            return;
+        }
+        int activityNum = homeActivities.size();
+        ComponentName[] set = new ComponentName[activityNum];
+        int defaultMatch = -1;
+        for(int i = 0; i < activityNum; i++){
+
+            ResolveInfo info = homeActivities.get(i);
+            set[i] = new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
+            if(defaultLauncher.getClassName().equals(info.activityInfo.name)
+                    && defaultLauncher.getPackageName().equals(info.activityInfo.packageName)){
+                defaultMatch = info.match;
+            }
+        }
+        //if Flat Launcher is not found, do not set anything
+        if(defaultMatch == -1){
+            return;
+        }
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_MAIN);
+        filter.addCategory(Intent.CATEGORY_HOME);
+        filter.addCategory(Intent.CATEGORY_DEFAULT);
+
+        pm.addPreferredActivity(filter, defaultMatch, set, defaultLauncher);
+    }
+
+    public static void killLauncher(Context context, String packageName) {
+        try {
+            ActivityManager am = (ActivityManager)context
+                    .getSystemService(Context.ACTIVITY_SERVICE);
+            Method forceStopPackage = am.getClass()
+                    .getDeclaredMethod("forceStopPackage", String.class);
+            forceStopPackage.setAccessible(true);
+            forceStopPackage.invoke(am, packageName);
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    private static String getLauncherPackageName(Context context) {
+        final Intent intent = new Intent(Intent.ACTION_MAIN);
+        intent.addCategory(Intent.CATEGORY_HOME);
+        final ResolveInfo res = context.getPackageManager().resolveActivity(intent, 0);
+        if (res.activityInfo == null) {
+            // should not happen. A home is always installed, isn't it?
+            return null;
+        }
+        if (res.activityInfo.packageName.equals("android")) {
+            return null;
+        } else {
+            return res.activityInfo.packageName;
+        }
+    }
 }
diff --git a/src/org/codeaurora/snaplauncher/SwitchToFlatLauncherActivity.java b/src/org/codeaurora/snaplauncher/SwitchToFlatLauncherActivity.java
new file mode 100644
index 0000000..02bb55f
--- /dev/null
+++ b/src/org/codeaurora/snaplauncher/SwitchToFlatLauncherActivity.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.snaplauncher;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.KeyEvent;
+
+import com.android.launcher3.Utilities;
+
+public class SwitchToFlatLauncherActivity extends Activity{
+
+    private String mWillingKilledPackage = Utilities.FLAT_LAUNCHER_PACKAGENAME;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    }
+
+    @Override
+    protected void onResume(){
+        super.onResume();
+        showSetFlatLauncherAsHomeMsg();
+    }
+
+    @Override
+    public void onDestroy(){
+        super.onDestroy();
+        Utilities.killLauncher(getApplicationContext(), mWillingKilledPackage);
+    }
+
+    private void showSetFlatLauncherAsHomeMsg() {
+        AlertDialog dialog = new AlertDialog.Builder(this)
+                .setMessage(getResources().getString(R.string.set_flat_launcher_as_home_msg))
+                .setOnKeyListener(new Dialog.OnKeyListener() {
+                    @Override
+                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                        if (keyCode == KeyEvent.KEYCODE_BACK) {
+                            finish();
+                        }
+                        return true;
+                    }
+                })
+                .setNegativeButton(getResources().getString(R.string.dialog_cancel),
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                finish();
+                            }
+                        })
+                .setPositiveButton(getResources().getString(R.string.dialog_ok),
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                startFlatLauncherAndSetDefault();
+                                mWillingKilledPackage =  Utilities.LAUNCHER_PACKAGENAME;
+                                finish();
+                            }
+                        })
+                .show();
+        dialog.setCanceledOnTouchOutside(false);
+    }
+
+    private void startFlatLauncherAndSetDefault(){
+        Intent intent = new Intent();
+        ComponentName component=new ComponentName(Utilities.FLAT_LAUNCHER_PACKAGENAME,
+                Utilities.LAUNCHER_CLASSNAME);
+        intent.setComponent(component);
+        startActivity(intent);
+        //set Launcher3 as the preferred home activity
+        Utilities.setupDefaultLauncher(getPackageManager(), getApplicationContext(), component);
+    }
+}
diff --git a/src/org/codeaurora/snaplauncher/SwitchToLauncher3Activity.java b/src/org/codeaurora/snaplauncher/SwitchToLauncher3Activity.java
new file mode 100644
index 0000000..34ae8e1
--- /dev/null
+++ b/src/org/codeaurora/snaplauncher/SwitchToLauncher3Activity.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials provided
+ *    with the distribution.
+ *  * Neither the name of The Linux Foundation nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.codeaurora.snaplauncher;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.ComponentName;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.KeyEvent;
+
+import com.android.launcher3.Utilities;
+
+public class SwitchToLauncher3Activity extends Activity{
+
+    private String mWillingKilledPackage = "";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        showSetLauncher3AsHomeMsg();
+    }
+
+    @Override
+    public void onDestroy(){
+        super.onDestroy();
+        if (mWillingKilledPackage.equals(Utilities.FLAT_LAUNCHER_PACKAGENAME)){
+            Utilities.killLauncher(getApplicationContext(),
+                    Utilities.FLAT_LAUNCHER_PACKAGENAME);
+        }
+    }
+
+    private void showSetLauncher3AsHomeMsg() {
+        AlertDialog dialog = new AlertDialog.Builder(this)
+                .setMessage(getResources().getString(R.string.set_launcher3_as_home_msg))
+                .setOnKeyListener(new Dialog.OnKeyListener() {
+                    @Override
+                    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
+                        if (keyCode == KeyEvent.KEYCODE_BACK) {
+                            finish();
+                        }
+                        return true;
+                    }
+                })
+                .setNegativeButton(getResources().getString(R.string.dialog_cancel),
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                finish();
+                            }
+                        })
+                .setPositiveButton(getResources().getString(R.string.dialog_ok),
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                startLauncher3AndSetDefault();
+                                mWillingKilledPackage = Utilities.FLAT_LAUNCHER_PACKAGENAME;
+                                finish();
+                            }
+                        })
+                .show();
+
+        dialog.setCanceledOnTouchOutside(false);
+    }
+
+    private void startLauncher3AndSetDefault(){
+        Intent intent = new Intent();
+        ComponentName component=new ComponentName(Utilities.LAUNCHER_PACKAGENAME,
+                Utilities.LAUNCHER_CLASSNAME);
+        intent.setComponent(component);
+        startActivity(intent);
+        //set Launcher3 as the preferred home activity
+        Utilities.setupDefaultLauncher(getPackageManager(), getApplicationContext(), component);
+    }
+}